Skip to content

Modularize all the things #6598

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

Closed
wants to merge 23 commits into from
Closed

Modularize all the things #6598

wants to merge 23 commits into from

Conversation

headius
Copy link
Member

@headius headius commented Mar 6, 2021

This PR will include changes necessary to fully JPMS modularize JRuby.

@headius headius added this to the JRuby 9.3.0.0 milestone Mar 6, 2021
@headius
Copy link
Member Author

headius commented Mar 9, 2021

I have started to try to modularize JRuby itself by adding a proper module-info.java. The related commit spells out the changes, but there is one issue I have been unable to remedy...

There is a new compile-time error about the classes Main and CallSite, saying they conflict with a package of the same name. There is in each case a matching package name, but in lowercase, and this has never been an issue before.

https://gist.github.com/headius/14a50f446ab9d0f6976a231c8ec0f915

I will be unable to progress until this issue can be fixed. I have not been able to reproduce in a sample project and nobody so far has been able to explain why this breaks.

@headius
Copy link
Member Author

headius commented Mar 16, 2021

The issue that stopped me from proceeding has been reported as an OpenJDK bug. We will need to find a workaround until the patched versions have become commonplace.

@headius
Copy link
Member Author

headius commented Mar 16, 2021

@headius
Copy link
Member Author

headius commented May 24, 2021

This is very close. There are a few items that mean we have to punt the remaining work until 9.4.

  • Due to JDK-8263432, we have to build with Java 17. That is clearly not acceptable.
  • A few libraries do not even have module names yet:
    • jzlib will have to be forked, see https://github.com/jruby/jzlib which has a WIP branch to add module name.
    • ant is an open issue. It has not been modularized by the Apache maintainers, and there does not appear to be any plan to do so.
  • Most of the libraries that do have modules names are doing them automatically, which limits our ability to use tools like jlink. With more time we can get full module descriptors installed.

Of these, the first is the biggest issue. I have commented on the JDK issue asking for a workaround but have not year heard back.

@headius
Copy link
Member Author

headius commented Nov 4, 2022

Updated the PR for latest master and made some additional tweaks, but we're not quite there yet.

Tweaks:

  • Port the module logic from jruby.bash in original commits to jruby.sh. Also replaced --module-path with -p and now using the -m flag to set the main module and class.

Manual changes needed to run JRuby after build:

  • Apache Ant does not have a module, so it gets assigned a module name based on the jar file. During the build, that module is ant so we have to use that in the module-info, but once the jar files get copied to lib/modules the module name changes to org.apache.ant.ant. If the file is moved to ant.jar then it works again, but this is a messy problem.
  • jffi pulls in two org.hamcrest jars that are not modularized and that have a split package. These jars are a development dependency of jffi but are not necessary to run it, so they should not get copied to our module dir. Deleting them allows you to proceed.

Once this is all set up, JRuby will at least start to bootstrap itself, but due (I think) to the way we load classloader resources, the JRuby kernel can't boot completely:

$ jruby -e 1
LoadError: no such file to load -- jruby/java.rb

Skipping the kernel load gets closer, but the main script gets compiled into a class in the default package, which is not liked by JPMS:

$ jruby -Xdebug.parser -e 1
2022-11-04T09:51:01.081-05:00 [main] WARN FilenoUtil : Native subprocess control requires open access to the JDK IO subsystem
Pass '--add-opens java.base/sun.nio.ch=org.jruby.base --add-opens java.base/java.io=org.jruby.base' to enable.
Unhandled Java exception: java.lang.IllegalAccessError: class DashE (in unnamed module @0x297c9a9b) cannot access class org.jruby.RubyModule (in module org.jruby.base) because module org.jruby.base does not export org.jruby to unnamed module @0x297c9a9b
java.lang.IllegalAccessError: class DashE (in unnamed module @0x297c9a9b) cannot access class org.jruby.RubyModule (in module org.jruby.base) because module org.jruby.base does not export org.jruby to unnamed module @0x297c9a9b
                  <clinit> at -e:-1
   ensureClassInitialized0 at jdk/internal/misc/Unsafe.java:-2
    ensureClassInitialized at jdk/internal/misc/Unsafe.java:1042
          newFieldAccessor at jdk/internal/reflect/UnsafeFieldAccessorFactory.java:43
          newFieldAccessor at jdk/internal/reflect/ReflectionFactory.java:186
      acquireFieldAccessor at java/lang/reflect/Field.java:1105
          getFieldAccessor at java/lang/reflect/Field.java:1086
                       set at java/lang/reflect/Field.java:780
        defineFromBytecode at org/jruby/ir/targets/JVMVisitor.java:132
  defineScriptFromBytecode at org/jruby/ir/targets/JVMVisitor.java:122
                   execute at org/jruby/ir/Compiler.java:65
                   execute at org/jruby/ir/Compiler.java:32
                   execute at org/jruby/ir/IRTranslator.java:42
                tryCompile at org/jruby/Ruby.java:1244
             precompileCLI at org/jruby/Ruby.java:1211
               runNormally at org/jruby/Ruby.java:1173
               runNormally at org/jruby/Ruby.java:1166
               runNormally at org/jruby/Ruby.java:1202
               runFromMain at org/jruby/Ruby.java:981
             doRunFromMain at org/jruby/Main.java:398
               internalRun at org/jruby/Main.java:282
                       run at org/jruby/Main.java:227
                      main at org/jruby/Main.java:199

If we also disable JIT compilation, so that the target script does not compile, then the code runs but there's some undiagnosed issue with acquiring Java IO internals, even though we are passing the correct flags at the command line:

$ jruby -Xdebug.parser -X-C -e 1
2022-11-04T10:00:20.876-05:00 [main] WARN FilenoUtil : Native subprocess control requires open access to the JDK IO subsystem
Pass '--add-opens java.base/sun.nio.ch=org.jruby.base --add-opens java.base/java.io=org.jruby.base' to enable.

So we are getting there but have a number of additional items to work on. I've also noticed that incremental rebuilds seem to fail to find our AnnotationBinder class. I have to clean build each time.

Here's the --environment output currently showing the eventual command line with all module stuff:

JRuby Environment
=================

JRuby executable:
  /home/headius/work/jruby/bin/jruby
JRuby command line options:
  --environment
Current directory:
  /home/headius/work/jruby

Environment:
  JRUBY_HOME: /home/headius/work/jruby
  JRUBY_OPTS: 
  JAVA_OPTS: 
  JAVACMD: /usr/lib/jvm/java-11/bin/java
  JAVA_HOME: /usr/lib/jvm/java-11

Detected Java modules at /usr/lib/jvm/java-11

Adding Java options from: /home/headius/work/jruby/bin/.jruby.java_opts

Adding Java options from: /home/headius/work/jruby/bin/.jruby.module_opts
  --add-opens java.base/java.io=org.jruby.base
  --add-opens java.base/java.nio.channels=org.jruby.base
  --add-opens java.base/sun.nio.ch=org.jruby.base
  --add-opens java.management/sun.management=org.jruby.base

Java command line:
  /usr/lib/jvm/java-11/bin/java @/home/headius/work/jruby/bin/.jruby.java_opts @/home/headius/work/jruby/bin/.jruby.module_opts -Xss2048k -Djffi.boot.library.path=/home/headius/work/jruby/lib/jni -Djava.security.egd=file:/dev/urandom -p /home/headius/work/jruby/lib/modules -classpath /home/headius/work/jruby/lib/jruby.jar: -Djruby.home=/home/headius/work/jruby -Djruby.lib=/home/headius/work/jruby/lib -Djruby.script=jruby -Djruby.shell=/bin/sh -m org.jruby.base/org.jruby.Main

@headius
Copy link
Member Author

headius commented Nov 4, 2022

Given the remaining issues and the challenge of fixing them while still supporting traditional non-modularized Java, I'm punting this to the next major release. That version will commit to a minimum Java of at least 11 and possibly 17, making the module changes both necessary and easier to deal with.

@headius headius modified the milestones: JRuby 9.4.0.0, JRuby 9.5.0.0 Nov 4, 2022
* Use newer backport9 to access Java 8 StackWalker
* Add module-info for modules we require
* Copy jruby-base jar and deps into lib/modules
* Modify jruby.bash to handle unshaded jruby and deps as classpath
  or module path entries
* Restructure build for module-info.java

There's a remaining issue here to build: CallSite and Main have
sibling packages with the same name as lowercase, and that appears
to be rejected by the build currently.
@headius headius changed the base branch from master to 9.5-dev January 11, 2024 07:03
Ant is no longer maintained, and as a result there's no module-
based version of its jar. We must move this out to a separate
library that can be used at build time, such as during JRuby's own
uses of the Rake ant targets.
We only have this dependency due to the @generated annotation we
add to some generated sources, but neither we nor anyone else ever
consumes that annotation.
Default scope for copy-dependencies is "test", which copies all
runtime, provided, and test dependencies. We only want runtime in
lib/modules.
This patch makes it possible to boot JRuby fully modularized. A
few notes:

* The org.jruby.base module is now open, because I was too lazy
  to individually open all of the Ruby kernel paths and there is
  no way to open them recursively from module-info.
* Ruby "kernel" sources have been moved into org.jruby.kernel to
  aid in accessing them in a module-friendly way. This does,
  unfortunately, result in paths like
  org/jruby/kernel/kernel/kernel.rb. An alternative name may be in
  order.
Using lookup() appears to return a Lookup object that is stricter
about access restrictions from a parent module to a child
classloader with no module. In this case, the variables in the
reified object classes are to be wired up in accessors. Using the
lookup() version results in an error:

java.lang.IllegalAccessException: symbolic reference class is not accessible: class org.jruby.gen.RubyObject5, from class org.jruby.specialized.RubyObjectSpecializer (module org.jruby.base)
Without this you cannot incrementally build. For some reason clean
build still works.
* Drop another Ant reference in favor of Java 11 Files.readString.
* Remove unnecessary and absent java.xml.ws.annotation module.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy