setup-ruby icon indicating copy to clipboard operation
setup-ruby copied to clipboard

Preinstalled jruby-launcher causing warnings on Java 8

Open headius opened this issue 5 months ago • 2 comments

Ensure the following before filing this issue

  • [x] I verified it reproduces with the latest version with - uses: ruby/setup-ruby@v1 (see Versioning policy)

  • [x] I tried to reproduce the issue locally by following the workflow steps (including all commands done by ruby/setup-ruby, except for Downloading Ruby & Extracting Ruby), and it did not reproduce locally (if it does reproduce locally, it's not a ruby/setup-ruby issue)

Are you running on a GitHub-hosted runner or a self-hosted runner?

GitHub-hosted runner

Link to the failed workflow job (must be a public workflow job, so the necessary information is available)

https://github.com/jruby/warbler/pull/559/checks#step:6:29

Any other notes?

Release builds of JRuby used by setup-ruby appear to have jruby-launcher preinstalled, but I cannot determine where this is happening. We do not pre-install it in our distribution archives, since it builds a native executable that would not work across platforms. It would be preferable on all platforms to leave the existing shell-based launcher in place, except on Windows where the provided jruby.exe will be used.

I would have filed this with ruby-builder but there's no way to file issues there. However it doesn't look like ruby-builder is doing it either. I'm not sure how this is getting installed, but it should not be.

headius avatar Jun 25 '25 01:06 headius

It's from https://github.com/rbenv/ruby-build/blob/1195268593b80a0a1bcd518e11efb4b4de115984/bin/ruby-build#L873. And it's intentional that jruby-launcher is installed for setup-ruby, as the shell launcher is IIRC significantly slower and also IIRC sometimes handles arguments incorrectly (e.g. its parsing of JVM arguments is likely not complete). EDIT: indeed: https://github.com/rbenv/ruby-build/issues/2550#issuecomment-3176274745

https://github.com/jruby/warbler/pull/559/checks#step:6:29

This link seems the wrong one, I see no warnings there, the linked line has Installing json 1.8.6 (java) and the previous step has Run gem uninstall -a jruby-launcher.

I think it would be best to fix jruby-launcher to avoid these warnings.

eregon avatar Jun 25 '25 07:06 eregon

https://github.com/jruby/warbler/actions/runs/15864738772/job/44729390048#step:6:29 seems the correct link.

Ignoring jruby-launcher-2.0.1-java because its extensions are not built. Try: gem pristine jruby-launcher --version 2.0.1

How can this happen? And apparently only on Java 8? Does JRuby include the JDK version into the ABI and so doesn't find the extension when switching JDK versions?

It sounds like a jruby or warbler or jruby-launcher bug to me. AFAIK it has never been seen/reported before, so might be warbler-specific somehow, a JRuby regression, or due to the explicit setup-java maybe.

eregon avatar Jun 25 '25 07:06 eregon

shell launcher is IIRC significantly slower and also IIRC sometimes handles arguments incorrectly

Neither of these things are true. We have refined that launcher over the years to be very lightweight (and compatible with Bourne shell), and any inability to handle command line arguments has been fixed. If there are additional issues, I do not know them, but we would fix them.

The native launcher actually comes in two forms these days.

The first form, which produces a Windows executable, legs behind on features and is maintained only so we have an exe and because .bat and .CMD are dreadful scripting languages. We used to use this everywhere, until I realized we were never going to keep up with the features of the shell script.

The second form, introduced recently for Unix environments, just launches the shell script with /bin/sh.

The shell script introduces a very small amount of overhead compared to executing directly, but it's on the order of a few milliseconds.

How can this happen?

It is a rubygems issue. When installing any gem that has an extension builder, RG will mark that the extension has been built only for the current platform. It includes the Java version in that platform. So if it's built for one Java version and you switch to another, even though it doesn't need to be rebuilt, it warns.

The problem is not using the native executable launcher versus the shell launcher. As I described above, the problem is that pre-installing the launcher ties it to a specific Java version, and then ruby gems warns if it is used on a different Java version.

headius avatar Jun 25 '25 16:06 headius

Comparison of using the shell launcher versus directly running the java command line it produces:

$ time jruby --dev -e 1
jruby --dev -e 1  0.92s user 0.07s system 120% cpu 0.821 total
$ time /Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home/bin/java @/Users/headius/work/jruby/bin/.jruby.java_opts @/Users/headius/work/jruby/bin/.dev_mode.java_opts @/Users/headius/work/jruby/bin/.jruby.module_opts -Xss2048k -Djffi.boot.library.path=/Users/headius/work/jruby/lib/jni -Djava.security.egd=file:/dev/urandom -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=/Users/headius/work/jruby/lib/jruby-java21.0.5.jsa -Xlog:cds=off -Xlog:cds+dynamic=off --module-path /Users/headius/work/jruby/lib/jruby.jar -classpath /Users/headius/work/jruby/lib/jruby-prism.jar: -Djruby.home=/Users/headius/work/jruby -Djruby.lib=/Users/headius/work/jruby/lib -Djruby.script=jruby -Djruby.shell=/bin/sh org.jruby.Main -e 1
/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home/bin/java           0.99s user 0.12s system 137% cpu 0.803 total

Less than 20ms difference, which is consistent for me on most platforms.

And here's the RubyGems issue: https://github.com/rubygems/rubygems/issues/3520

headius avatar Jun 25 '25 16:06 headius

FWIW the native launcher is sometimes necessary on non-Linux where a shell script cannot be in another script's shebang.

Here's the PR that changed the native launcher to just exec /bin/sh: https://github.com/jruby/jruby-launcher/pull/48

headius avatar Jun 25 '25 17:06 headius

Neither of these things are true.

I'm pretty sure they were true in the past, because I experienced them first hand. Things might have improved and changed, good. In fact I also recall there were separate jruby.sh and jruby.bash, as is the case e.g. in 9.3: https://github.com/jruby/jruby/tree/9.3.0.0/bin.

I also recall the project to use mruby-cli for the jruby launcher, I guess that was abandoned? I recall having to deal with all these variants of the launcher for JRuby+Truffle, it was not fun.

The second form, introduced recently for Unix environments, just launches the shell script with /bin/sh.

That's nice. It's quite recent though so only affects JRuby releases built since then.

It is a rubygems issue.

But maybe JRuby shouldn't include the Java version in the ABI? You would have the problem for any other gem installed on some JDK and then used on another JDK.

The problem is not using the native executable launcher versus the shell launcher. As I described above, the problem is that pre-installing the launcher ties it to a specific Java version, and then ruby gems warns if it is used on a different Java version.

I think JRuby should ship with a native launcher already in the archive (and obviously then one archive per platform), then we wouldn't have this problem. And maybe with a JDK too, optionally for convenience and reliability. Then it would be so much easier to install JRuby. I had to workaround the launcher on Windows with https://github.com/jruby/jruby-launcher/issues/29 and that's still not solved upstream 5 years later. I already spent too much time dealing with JRuby launcher issues, CRuby and TruffleRuby had 0 launcher issues.

I think https://github.com/rubygems/rubygems/issues/3520 sounds unlikely to be fixed soon, and even if it was it wouldn't affect previous RubyGems versions of course. Maybe the jruby-launcher gem could declare no C extensions? That's probably difficult though, as then I guess there is no hook to run arbitrary code to e.g. compile and install the launcher to the right place. Maybe it shouldn't be a gem, but then probably it should just be shipped in the JRuby archive, either already compiled, or with some extra executable (which could be a Bash script) like compile-jruby-launcher or so, or even as a default gem which might allow more flexibility.

eregon avatar Jun 25 '25 18:06 eregon

Anyway, I understand the problem now.

I think if you want people to no longer gem install jruby-launcher, then you should make that gem a noop and specifically have no native extensions. That would avoid these warnings from RubyGems, and solve the problem going forward. And it would make sense to update ruby installers like ruby-build to no longer gem install jruby-launcher then, although older versions might still benefit from it maybe. This will solve it for all future JRuby releases.

But I don't see any solution for existing releases here. The existing JRuby release archives at https://github.com/ruby/ruby-builder/releases include the native launcher and we have have never rebuilt those unless there is a very critical issue. Rebuilding also implies some time during which the versions are unavailable and potentially breaking CIs. This is hardly critical, it only happens when using setup-java with a different version, for older JRuby releases, and it can be worked around by either gem uninstall jruby-launcher or gem update jruby-launcher.

eregon avatar Jun 25 '25 19:06 eregon

I also recall the project to use mruby-cli for the jruby launcher, I guess that was abandoned?

We try many ideas. Some work, some don't. What does it matter to you?

I recall having to deal with all these variants of the launcher for JRuby+Truffle

That was over a decade ago. Things change.

But maybe JRuby shouldn't include the Java version in the ABI?

We present "universal-java<version>" as arch in RbConfig::CONFIG. This started to be used by RubyGems for marking extensions as built without any input from us. We would not have chosen a Java-version-specific indicator for RubyGems to use had we been given the option.

I think JRuby should ship with a native launcher already in the archive And maybe with a JDK too, optionally for convenience and reliability.

We won't do that. Our standard release archives work anywhere there's a JDK, and we have no plans to start shipping new platform-specific native dependencies or prebuilt JDKs with JRuby.

We do ship Docker images for a set of JDK versions, but that just involves publishing some Dockerfiles.

I had to workaround the launcher on Windows with https://github.com/jruby/jruby-launcher/issues/29 and that's still not solved upstream 5 years later.

I'll see what I can do about that, but I'm not clear what is the current issue since you mention it has been worked around.

I already spent too much time dealing with JRuby launcher issues

Then add me as a maintainer and I will deal with them.

I think if you want people to no longer gem install jruby-launcher

That's not what I said. I said it should not be preinstalled because it can result in these warnings and it is generally unnecessary.

And it would make sense to update ruby installers like ruby-build

I have opened https://github.com/rbenv/ruby-build/issues/2545 to discuss a path forward.

But I don't see any solution for existing releases here.

That's fine, now that I know it needs to be fixed in ruby-build I'll fix it there.

headius avatar Jun 25 '25 19:06 headius

Then add me as a maintainer and I will deal with them.

ruby-builder is too sensitive since it affects all builds of *Ruby used in GitHub actions. Only I and hsbt have write access to that repo, by design.

jruby-dev-builder you already have access.

For setup-ruby, I think you know it too little currently to merge PRs by yourself, given the recent-ish long discussions to explain things and being apparently not so eager to find things out by yourself (e.g., I had to point to you where jruby-launcher is installed). But of course you can always make PRs. It would be best to spend some time to understand well the design of the area you are changing though. In general, if someone spends the time to make a proper fix or analyze an issue without asking me to investigate for them, I will be open to merge their contribution or help. In your recent issues/PRs on this repo I feel I had to spend more time than you, which is not good.

eregon avatar Jun 25 '25 19:06 eregon

I had to point to you where jruby-launcher is installed

setup-ruby says that prebuilt dists are created by ruby-builder. I assumed that meant that the dists are created by ruby-builder. Perhaps the documentation should state that they are actually created by ruby-build, so others can see where the dist building actually happens.

As I mentioned in my original report:

I would have filed this with ruby-builder but there's no way to file issues there. However it doesn't look like ruby-builder is doing it either. I'm not sure how this is getting installed, but it should not be.

All you had to do was point out that ruby-builder uses ruby-build and that's where the launcher is installed. Instead you went on a philosophical rant about how we do things, how hard it has been for you, how you think we should do them instead. None of that was relevant to the issue.

I would be happy to learn how to maintain setup-ruby and take the JRuby issues off your hands. If that's not an option, don't berate me every time I file an issue.

headius avatar Jun 25 '25 20:06 headius