Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Access to default methods in
@JImplements
#1182Access to default methods in
@JImplements
#1182Changes from 5 commits
d6dbda2
49c3bde
902156a
b45f56c
27ae31c
feeda0c
3026af0
1efd1d8
9a2a604
9d66c27
8bfb5b0
49c32bc
0fd5338
9bd2cd0
51aee96
b5cdd55
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the heart of the change as we need to call these privileged methods to invoke a special method. Of course given the method we are trying to invoke is nothing more than a public method implemented in the interface there is absolutely nothing privileged about the call. The issue is simply that the API through which we are accessing a public method can also be used to invoke private methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't using MethodHandles.publicLookup be better here since it can only access public fields/methods thus removing the privileged issue?
I'm sure there are some possible benefits to having a java agent, I just wanted to point this out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can certainly try that. Though we will still need the agent if we want to make sure that it never changes behavior based on how JPype is started. (Something that plagues the development.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other reason for requiring privilege is if we ever want to be able to "extend" a class in Python. In that case we will need to get to protected methods, and protected fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually have a prototype using JDK22 ClassFile API preview feature, as an independent python package, where I managed this. I designed it around the impression that if you want to extend a Java class from Python, then you don't care about the added overhead 😅.
I basically created delegate methods that start with "-" which could only be accessed by reflection or it would be a syntax error. It's gross but it worked.
I was considering integrating and contributing it since it would not introduce GPL code. Was just waiting on it to exit preview in a LTS JDK and then for the free time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to call a default method from jni using
CallNonvirtualObjectMethodA
if you use the interface with the default method as the claz parameter.I figured this out while working on
super()
support for extension classes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CallNonvirtualObjectMethodA does not work. I ran tests on it. While it does allow the default method to be called, it ALWAYS calls the default even when overwritten. I thus went with this approach as there are no methods in the JNI interface that gave proper behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that is what the NonVirtual does, it's invoke exactly the specified method. Thinking about it, I'm not sure why the regular CallVirtual doesn't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason it doesn't is that for interfaces "ALL" virtual method route to the proxy dispatch. As default methods are virtual that means they effectively are not reachable other than by the "NonVirtual" method. We could in principle your the virtual call request to our method, then call to Python with a reference handle find out that it was really supposed to go to default, then reroute back in the JNI method for a NonVirtual call. That would mean unpacking and repacking arguments at C level and keeping track of the default level in C. Of course we would have to know to try the nonvirtual path (trying to call it when it doesn't exist is a segfault). So that means everything needs to be handed to the the C method. I attempted that path but found it distasteful as it required making reflection API calls prior to launching to C.
It is "doable" but means more routing on the primary path to check for and passing the default method down to C. That would make this already slow path potentially even slower for a feature that not many people will likely use. Better to reroute back to Java and try to invoke the handle there.