GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — NoSuchMethodError on JDK8 with Clojure · Issue #116 · lmdbjava/lmdbjava

NoSuchMethodError on JDK8 with Clojure #116

New issue
Copy link
New issue
Copy link
Closed
Closed
NoSuchMethodError on JDK8 with Clojure#116
Copy link

Description

@miner
miner
opened on Jan 5, 2019
Issue body actions

I'm using lmdbjava for a Clojure project. I don't think Clojure matters for this issue but it's the latest version 1.10. My project was working fine with lmdbjava 0.6.1, but failed when I tried to update to lmdbjava 0.6.2.

(This is a small bit of Clojure test failure report.)
ERROR in (larger-test) (ByteBufferProxy.java:297)
Uncaught exception, not in assertion.
expected: nil
actual: java.lang.NoSuchMethodError: java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer;
at org.lmdbjava.ByteBufferProxy$UnsafeProxy.out (ByteBufferProxy.java:297)
org.lmdbjava.ByteBufferProxy$UnsafeProxy.out (ByteBufferProxy.java:260)
org.lmdbjava.KeyVal.valOut (KeyVal.java:133)
org.lmdbjava.Dbi.reserve (Dbi.java:465)

I'm using java version "1.8.0_192"
Java(TM) SE Runtime Environment (build 1.8.0_192-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.192-b12, mixed mode)

Interestingly, my Clojure project works on JDK 11 with either lmdbjava 0.6.1 and 0.6.2. I got it to work with JDK 8 by building lmdbjava 0.6.2 and installing it in my local maven repository. It looks like the maven central jar was built with JDK 11 so maybe that explains my problem? I'm guessing that some mvn option to target 1.8 would help, but this is just speculation. If other people can confirm that the maven central jar works with JDK 8, then I will have to investigate the Clojure inter-op problem.

Would you be willing to target JDK 8 or is that a non-starter?

Activity

  1. ivenhov commented on Jan 6, 2019

    @ivenhov
    ivenhov
    on Jan 6, 2019
    More actions

    I got the same on Java 1.8.0_181. Works ok on LMDB 0.6.1

    Exception in thread "main" java.lang.NoSuchMethodError: java.nio.ByteBuffer.clear()Ljava/nio/ByteBuffer; at org.lmdbjava.ByteBufferProxy$UnsafeProxy.out(ByteBufferProxy.java:297) at org.lmdbjava.ByteBufferProxy$UnsafeProxy.out(ByteBufferProxy.java:260) at org.lmdbjava.KeyVal.valOut(KeyVal.java:133) at org.lmdbjava.Dbi.get(Dbi.java:239)

    possibly related

    akka/akka-core#23755

  2. miner commented on Jan 6, 2019

    @miner
    miner
    on Jan 6, 2019
    Author
    More actions

    Thanks for the confirmation of the problem in pure Java. Following the akka link and related items, I found a good explanation here: https://jira.mongodb.org/browse/JAVA-2559

    Java 9 introduces overridden methods with covariant return types for the following methods in java.nio.ByteBuffer that are used by the driver:

    position
    limit
    flip
    clear

    In Java 9 they all now return ByteBuffer, whereas the methods they override return Buffer,
    resulting in exceptions like this when executing on Java 8 and lower:

    java.lang.NoSuchMethodError: java.nio.ByteBuffer.limit(I)Ljava/nio/ByteBuffer

    This is because the generated byte code includes the static return type of the method, which is not found on Java 8 and lower because the overloaded methods with covariant return types don't exist.

    The solution is to cast ByteBuffer instances to Buffer before calling the method.

  3. miner commented on Jan 6, 2019

    @miner
    miner
    on Jan 6, 2019
    Author
    More actions

    It seems like the casting works, but for long term compatibility I suggest that you try to target 1.8 and use the 1.8 class path.

  4. vladp commented on Jan 27, 2019

    @vladp
    vladp
    on Jan 27, 2019
    More actions

    thx for pointing me to the duplicate issue.

    Does this mean 0.6.2 will not work with java 8 (and only java 9 or above is needed)?

    My code supprts freebsd/netbsd/dragonflybsd/openbsd and those do not have Java 9 or 11
    in their distros yet. So I am stuck with Java 8 at the moment.

  5. miner commented on Jan 27, 2019

    @miner
    miner
    on Jan 27, 2019
    Author
    More actions

    Yes, the 0.6.2 jar was built with JDK 11 so it will not work with JDK 8 (Java 1.8) systems. However, you can build the lmdbjava source on JDK 8 and then it will work. I did a local mvn install and everything worked for me on JDK 8. In theory, setting the build target to java 1.8 would make a compatible jar for 1.8+ but I haven't tested that.

  6. bp-alex commented on Jan 27, 2019

    @bp-alex
    bp-alex
    on Jan 27, 2019
    Member
    More actions

    LmdbJava's POM does not declare a particular Java version. Instead it inherits from the Acegi Standard Project POM and this was set to 1.8.

    All builds are performed by Travis and it currently supports Ubuntu releases Precise, Trusty and Xenial. These correspond to YY-MM date versions 12.04, 14.04 and 16.04 respectively.

    The Travis Xenial JVM environment only supports OpenJDK 10 and 11. LmdbJava 0.6.2 was built by OpenJDK 11 on Travis Xenial, although with Java 1.8 as the compilation target as mentioned earlier.

    While the Trusty JVM environment supports OpenJDK 8, I prefer to not use a distribution that is almost five years old as I write this.

    The real question is whether Java 8 is appropriate to support at all. I suggest there are three key questions:

    1. When does Java 8 reach EOL?
    2. Does LmdbJava support Java 11, being the next LTS release?
    3. Given LmdbJava 0.6.1 works with Java 8, does semantic versioning indicate 0.6.2 should as well?

    On the first point, the Oracle Java SE Support Roadmap states:

    Oracle will continue to provide free public updates and auto updates of Java SE 8, until at least the end of December 2020 for Personal Users, and January 2019 for Commercial Users.

    I don't think many LmdbJava users would concurrently be both Personal Users and unable to update beyond Java 8. While Commercial Users are likely to have constraints in doing so, such users are EOL as of this month. So I don't honestly think we need to support Java 8 given this month it's EOL for Commercial Users and I believe Personal Users can probably upgrade. I am sympathetic to the BSD issue faced by @vladp but it's an unusual circumstance and it would seem preferable to help the BSDs upgrade their JVM given Java 8's EOL status.

    On the second point, I am using LmdbJava with Java 11. There seem to be some issues with Windows as per #97 that we need to figure out and we need more discussion around the items in #42 but LmdbJava definitely works with Java 11 on Linux.

    On the third point, in my reading semantic versioning doesn't specify any requirements. However the core principle is developers should be able to take a PATCH version (so 0.6.1 to 0.6.2) without breaking their applications. So LmdbJava breaking for Java 8 between 0.6.1 and 0.6.2 is unacceptable.

    I'll be pragmatic here and change the Travis build back to Trusty to work around this. But I provided the above background because I don't really like using very old software (be it Ubuntu distributions or Java versions) and there will be a point in the not-too-distant future where Java 8 is no longer supported. Before doing that we'll have Java 11 working properly across all the officially-supported operating systems (ie those for which we ship the native library within the LmdbJava JAR) and of course make sure the change is obvious at a version number point of view.

  7. ivenhov commented on Jan 28, 2019

    @ivenhov
    ivenhov
    on Jan 28, 2019
    More actions

    Hi @benalexau
    Thanks for your time and elaborate explanation.
    I totally understand point of view and you arguments.
    Let me explain my situation.

    We are evaluating/using lmdbjava in commercial environment.
    We have hundreds of installs of our software (server-side) across the globe. Due to various constraints we cannot follow latest/greatest Ubuntu upgrades.
    There is certain risk, operational complexity, downtime associated with the upgrade etc.
    In some environments only security patches are allowed.
    We are on Ubuntu LTS and only this year we are switching to 16.04 and Java 8. Previously we were running 12.04 with Java 7.
    In our case we prefer long-term stability and platform that we know rather than upgrading to versions that inevitably would bring in some issues.

    There is still a lot of uncertainty with Java 9 modules, open source projects used as dependencies of dependencies not keeping up etc. Java 11 is still very fresh, definitely not for production use in my view.
    I would love to be on the latest version of Java but reality is more complex and we will see a lot of sw running on server-side for quite some time.

    From my point of view if there is no particular need to build lmdbjava and tie it to the latest Java I would prefer to have lowest reasonable Java version. If Java 7 is out of the picture, I think Java 8 is reasonable.
    I believe Xenial has Java 8 by default.
    If software runs on never JVM it will surely take advantage of it despite being compiled with byte-code
    compatible with Java 8.
    BTW JDK breaking interfaces like that ByteBuffer.clear() ConcurrentHashMap.keySet() is one of the examples of incompatibilities we have to live with. They always come up in the worst possible moment, usually in production system

    Of course we can always build lmdbjava ourselves, although I would much prefer to get it as Gradle dependency.

    I absolutely agree on the versioning point.

    Thanks again for your time and maintaining the project.
    Keep up great work.

    Regards
    Daniel

  8. miner commented on Jan 28, 2019

    @miner
    miner
    on Jan 28, 2019
    Author
    More actions

    Thanks to @benalexau for the thorough response. My understanding is that you need to set the target to the older Java and configure the compiler's boot classpath to match the target JRE. My guess is that even with a target of 1.8 it still compiled against the JRE 11 boot classpath. That would explain why the published jar had Java 11 dependencies. I'm personally OK with a requirement of a newer Java as long as it's documented. I filed the bug because it looked like this was an unintentional change. It would be nice to have Java 8 compatibility just because a lot of places still use it and compatibility would avoid nasty surprises, but it's completely understandable that an open source project would choose the Java version that works best for their development process. Thanks for taking a look at this issue.

  9. bp-alex commented on Jan 29, 2019

    @bp-alex
    bp-alex
    on Jan 29, 2019
    Member
    More actions

    Thanks @ivenhov and @miner for your comments.

    It turns out you can use Xenial with OpenJDK 8 as shown in the Travis build 581.1. Can you please try the latest snapshot JAR to confirm it works for you with Java 8?

  10. ivenhov commented on Jan 29, 2019

    @ivenhov
    ivenhov
    on Jan 29, 2019
    More actions

    Works for me. Tested on Oracle JDK 1.8.0_181 on Windows

  11. miner commented on Jan 29, 2019

    @miner
    miner
    on Jan 29, 2019
    Author
    More actions

    0.6.3-snapshot works for me on Java 8 (with Clojure 1.10).

  12. bp-alex commented on Feb 8, 2019

    @bp-alex
    bp-alex
    on Feb 8, 2019
    Member
    More actions

    Great to hear it works. I'll close this ticket and make an LmdbJava release shortly.

  13. bp-alex
    closed this as completedon Feb 8, 2019
  14. miner commented on Feb 8, 2019

    @miner
    miner
    on Feb 8, 2019
    Author
    More actions

    lmdbjava 0.6.3 release works for me. Thanks.

  15. bp-alex
    added a commit that references this issue on Jun 3, 2020

    Build with Java 8 due to ByteBuffer NoSuchMethodError (#116, #158)

    2f8527b
  16. docwhomc
    added a commit that references this issue on Aug 2, 2020

    Cast (region) header to Buffer before clearing

    6622d30
  17. james-watkin
    added a commit that references this issue on Dec 28, 2021

    Build with Java 8 due to ByteBuffer NoSuchMethodError (#116, #158)

    5bb0d15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.