-
-
Notifications
You must be signed in to change notification settings - Fork 922
JRuby adds Java proxy classes to the Java module even if they are not from JRubyClassLoader #8156
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
Comments
Interesting! Do you think you can come up with a small reproduction for us? |
Steps:
|
Having thought about it a little bit more:
|
After looking at your example I think I understand the problem. When a Java object enters Ruby with a class we haven't seen before, we need to set up the "proxy" class under our own There's no hard reason why we immediately add the constant entry for the class under Avoiding setting the constant also would not really affect users, since any subsequent access of the constant name would lazily pick up the class, and only from the classloader hierarchy JRuby uses for Java integration. An alternative, less aggressive change would be to only automatically add the constant entry when we know it's from our Java integration classloader. @kares @enebo What are your thoughts here? It's probably not something we can change in 9.4.x but for Java 10 we could consider not always setting up the |
Previously whenever we see a new type of Java object, we both set up the proxy class AND set the constant. If that object's class is not from the typical Java integration classloader hierarchy, it will pollute the Java:: module with a normally inaccessible entry. This change only sets up the constant when it is accessed through the normal package reference, rather than when first seen. Fixes jruby#8156
I pushed #8208 as an experiment in delaying when we set up the @barrkel If you are able to test that branch with your application, I'd appreciate it. |
Oh and I should temper expectations a bit... this may be too major of a change to do in a point release of JRuby 9.4.x, so it would either be guarded behind a configuration property (defaulting to non-lazy in 9.4.7.0) or only merged into JRuby 10 for release later this year. |
In order to avoid polluting the Java:: namespace with classes from other classloader hierarchies, we are modifying the proxy class setup process to not eagerly set a constant for newly-encountered classes. This property controls the behavior, defaulting to true for JRuby 9.4.x but likely to switch to false in a future release (probably JRuby 10). The constants will still be defined if accessed directly, as before. We just won't define them when we happen to see an object with an unfamiliar type. See jruby#8208 and the bug it fixed jruby#8156.
@barrkel I have a PR settling now that would allow to turn off the "eager" constant definition, so that only constants accessed directly (and loaded out of our classloader hierarchy) will be defined in the |
JRuby version 9.3.13.0
Platform 6.5.13-1rodete2
Expected behavior:
org.example.C
which is in a jar which is not on the class path, call thisC_jar
org.example.C
which is in a jar which is on the class path, call thisC_classpath
C_jar
is loaded viaURLClassLoader
and instantiated in Java code. This is done to isolate the different versions ofC
.C_jar
Java
module to reference the classC
, expecting to getC_classpath
(i.e.Java::OrgExample::C
)Actual behavior:
Java
module syntax to accessC
results inC_jar
Workaround:
Java
module syntax to accessC
before any Ruby expression which evaluates to an object of classC_jar
In Java.java,
generateClassProxy
callsaddToJavaPackageModule
without checking the class loader of the class it generated a proxy for. Effectively, manipulating values from non-JRubyClassLoader
classes pollutes theJava
module with incompatible classes.The text was updated successfully, but these errors were encountered: