New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java::JavaLang::NoClassDefFoundError (java/sql/Date) #6608
Comments
Aha... I suspect this is due to us moving more into modularity, and this class references things outside the jruby.base module. I think this can be worked around by adding a |
Why does it work on irb or through Ruby directly.... |
On JDK11 looks like --add-module was removed.
|
@fzakaria Sorry, it is |
Hmm I can't reproduce from command line nor irb:
|
(FWIW you don't need |
@headius okay! I got a lot of good information for you. I opened a fix. The # Detect Java 9+ by the presence of a jmods directory in JAVA_HOME
if [ -d "$JAVA_HOME"/jmods ]; then
is_java9=1
fi
add_log " JAVACMD: $JAVACMD"
add_log " JAVA_HOME: $JAVA_HOME"
if [ "$is_java9" ]; then
add_log
add_log "Detected Java modules at $JAVA_HOME/jmods"
fi On my non-Nix Java installation this makes sense. ❯ ls -l /usr/lib/jvm/java-11-openjdk-amd64/jmods | head -n 3
.rw-r--r-- 162M root 20 Jan 1:42 java.base.jmod
.rw-r--r-- 119k root 20 Jan 1:42 java.compiler.jmod
.rw-r--r-- 58k root 20 Jan 1:42 java.datatransfer.jmod Nix however places jmods in a different directory. ❯ ls -l /nix/store/s1n0y12md0b1mvsg4ly57d43xxwbjdzq-openjdk-11.0.9+11/lib/openjdk/jmods | head -n 3
.r--r--r-- 256M fmzakari 31 Dec 1969 java.base.jmod
.r--r--r-- 119k fmzakari 31 Dec 1969 java.compiler.jmod
.r--r--r-- 58k fmzakari 31 Dec 1969 java.datatransfer.jmod Digging into how the JDK is setup (JDK11 no longer has a JRE) https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/compilers/openjdk/jre.nix#L16 I see the following:
I found the bug in NixPkgs and opened up NixOS/nixpkgs#116009 I wonder if there's a better approach for the JRuby script to find the module path that is more resilient. |
This is investigation I've done in support of jruby/jruby#6608 where I noticed some funky issues with JRuby and module loading. Looks like that JRuby expects JAVA_HOME to have a directory called `jmod`, which is consistent with the Java Module system. Unfortunately, the top level directory for the `jre` or `jdk` /nix/store entry is not a valid JAVA_HOME since it is missing that directory. Instead it's set within `lib/openjdk`, and there is a passthru variable set accordingly. This fixes JRuby and follows many other derivations. A simple search in the code-base shows that there are many other packages that suffer this same bug.
Still super unclear why in irb it can resolve it without the use of |
NixOS/nixpkgs#116009 (comment) has a good description showing bug and then fixed. |
@fzakaria Aha! Yep, that makes perfect sense. At the very least, we are not loading properly as a module which means none of our module flags will be used and certain functionality we need to open up will not be available. I knew this would be a fragile way to detect the presence of modules but it worked okay up until now. We do need to find a better way to detect that we will be running on a module-enabled jvm, but I do not know the answer right now. There may be a better file we can look at, or a fast way to check the version via some command. Let's do some research and see what we can figure out. |
@headius here is what I came up with. ❯ JAVA_HOME=~/not-correct java -XshowSettings:properties -version 2>&1 | grep java.home
java.home = /nix/store/2xv65447vkq09bpx1mfci1cx2vdvp153-openjdk-headless-11.0.9+11/lib/openjdk Don't know if there's a slicker way to get jmod specifically. |
Detecting module support based on the existence of the jmods directory was fragile for at least two reasons: * The jmods directory is only present in some builds of the JDK (not JRE) that can be used to jlink new runtime environments. * Some distributions of the JDK may omit or relocate this directory, such as Nix's version (jruby#6608). Instead we detect modules using two other mechanisms that should reliably work on all modularized Java runtimes: * Check for JAVA_HOME/lib/modules, generated by the jlink process. * Check for a JAVA_HOME/release file with a MODULES entry. See https://stackoverflow.com/questions/66601929 for a summary of detection mechanism. Fixes jruby#6608. jruby-launcher will need a matching update.
I have pushed #6615 to address this after a very helpful thread on Twitter: https://twitter.com/headius/status/1370173969634975746 The The new logic will use the presence of a @fzakaria Could you give the updated jruby.bash from the PR a test in your environment? There is a third more complex but fairly robust mechanism we could add: running |
Detecting module support based on the existence of the jmods directory was fragile for at least two reasons: * The jmods directory is only present in some builds of the JDK (not JRE) that can be used to jlink new runtime environments. * Some distributions of the JDK may omit or relocate this directory, such as Nix's version (jruby#6608). Instead we detect modules using two other mechanisms that should reliably work on all modularized Java runtimes: * Check for JAVA_HOME/lib/modules, generated by the jlink process. * Check for a JAVA_HOME/release file with a MODULES entry. See https://stackoverflow.com/questions/66601929 for a summary of detection mechanism. Fixes jruby#6608. jruby-launcher will need a matching update.
This mirrors the changes done in jruby/jruby#6615 to fix jruby/jruby#6608.
This has been fixed on 9.2 and master (9.3) branches as well as in jruby-launcher 1.1.14. |
Environment Information
Provide at least:
Linux fmzakari-glaptop 5.7.17-1rodete5-amd64 #1 SMP Debian 5.7.17-1rodete5 (2021-01-08) x86_64 GNU/Linux
Expected Behavior
Attempting to call
to_java
on a RubyTime object and have it return a java.sql.Date object returns NoClassDefFoundError.What is perculiar is that I can clearly create a java.sql.Date, so it seems to be accessible via my classpath.
Here is a minimal reproduction with irb:
A bit of a headscratcher for me since right before the call to to_java, you can see it working.
Actual Behavior
I expect the cast to work.
If I change the JDK we are using to JDK8, I see that the results work as intended.
There is something funky here going on with module-loading.
The text was updated successfully, but these errors were encountered: