Skip to content
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

Can't call methods of private subclasses with java_method in java 12 #5841

Closed
yamam opened this issue Aug 20, 2019 · 2 comments · Fixed by #5843
Closed

Can't call methods of private subclasses with java_method in java 12 #5841

yamam opened this issue Aug 20, 2019 · 2 comments · Fixed by #5843
Milestone

Comments

@yamam
Copy link

@yamam yamam commented Aug 20, 2019

Environment

jruby 9.2.8.0 (2.5.3) 2019-08-12 a1ac7ff OpenJDK 64-Bit Server VM 12.0.2+10 on 12.0.2+10 +jit [mswin32-x86_64]

JavaTest.java

public class JavaTest {

    public interface PublicInterface {
        public void publicMethod(Integer a);
        public void publicMethod(Long a);
    }

    public PublicInterface publicMember = new PrivateSubclass();

    private class PrivateSubclass implements PublicInterface {
        public void publicMethod(Integer a) {System.out.println("publicMethod(Integer)");}
        public void publicMethod(Long a) {System.out.println("publicMethod(Long)");}
    }
}

test.rb

java_import 'JavaTest'
JavaTest.new.publicMember.java_method(:publicMethod, [java.lang.Integer.java_class]).call(1)

Expected Behavior

You can call methods of private subclasses with java_method in java 8.

$ javac JavaTest.java
$ jruby test.rb
publicMethod(Integer)

Actual Behavior

You can't call methods of private subclasses with java_method in java 12.

$ jruby test.rb
2019-08-20T09:36:29.010+09:00 [main] WARN FilenoUtil : Native subprocess control requires open access to sun.nio.ch
Pass '--add-opens java.base/sun.nio.ch=org.jruby.dist' or '=org.jruby.core' to enable.
TypeError: illegal access on 'publicMethod': class org.jruby.javasupport.JavaMethod (in module org.jruby.dist) cannot access a member of class JavaTest$PrivateSubclass with modifiers "public"
    call at org/jruby/RubyMethod.java:120
  <main> at test.rb:2
@headius

This comment has been minimized.

Copy link
Member

@headius headius commented Aug 20, 2019

Looks like this is a problem with how we determine whether we should set methods accessible.

The logic here basically turns off setAccessible when on Java 9 or higher:

private static boolean calculateSetAccessibleDefault() {

I'm going to look at changing this property back to always true and modify the logic that uses it to use our trySetAccessible logic.

@headius

This comment has been minimized.

Copy link
Member

@headius headius commented Aug 20, 2019

It looks like all places that use the JI_SETACCESSIBLE option (with the default "false" on Java 9+) are already using our safe trySetAccessible that's aware of modules. Changing this calculated default to "true" appears to work fine.

I'm going to push it to a PR to make sure it doesn't affect too much other code.

headius added a commit to headius/jruby that referenced this issue Aug 21, 2019
The logic previously was depending on the ji.setAccessible
property, which by default would simply refuse to set accessible
*at all* when the Java version was >= "1.9" (also showing this
logic was introduced very early in the Java 9 development cycle.)

That default is removed here, along with a the CAN_SET_ACCESSIBLE
static field in RubyInstanceConfig deprecated and replaced with
the original meaning of this property, simply whether to attempt
setAccessible.

The direct calls to setAccessible have been replaced by the
trySetAccessible in backport9 library that checks if the target
member's module is open to JRuby, allowing users to opt-in to that
reflective access if their application needs it. Previously these
cases still skipped setAccessible just due to being on Java 9+.

Most of the changes here were masked by the property, but I have
also fixed several others that were not guarded by the property
or that were otherwise used in booting JRuby or extending Java
integration.

This fixes jruby#5841 by allowing `java_method` Method objects to
go ahead and trySetAccessible when the module is open.

This relates to jruby#5821, which fixed in 9.2.8 a similar issue where
even an open module would not set fields and methods accessible.
@headius headius added this to the JRuby 9.2.9.0 milestone Aug 21, 2019
Adithya-copart added a commit to Adithya-copart/jruby that referenced this issue Aug 25, 2019
The logic previously was depending on the ji.setAccessible
property, which by default would simply refuse to set accessible
*at all* when the Java version was >= "1.9" (also showing this
logic was introduced very early in the Java 9 development cycle.)

That default is removed here, along with a the CAN_SET_ACCESSIBLE
static field in RubyInstanceConfig deprecated and replaced with
the original meaning of this property, simply whether to attempt
setAccessible.

The direct calls to setAccessible have been replaced by the
trySetAccessible in backport9 library that checks if the target
member's module is open to JRuby, allowing users to opt-in to that
reflective access if their application needs it. Previously these
cases still skipped setAccessible just due to being on Java 9+.

Most of the changes here were masked by the property, but I have
also fixed several others that were not guarded by the property
or that were otherwise used in booting JRuby or extending Java
integration.

This fixes jruby#5841 by allowing `java_method` Method objects to
go ahead and trySetAccessible when the module is open.

This relates to jruby#5821, which fixed in 9.2.8 a similar issue where
even an open module would not set fields and methods accessible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

2 participants
You can’t perform that action at this time.