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

Getting JRebel to work with -agentpath on openJ9 #2751

Closed
andresluuk opened this issue Aug 30, 2018 · 8 comments
Closed

Getting JRebel to work with -agentpath on openJ9 #2751

andresluuk opened this issue Aug 30, 2018 · 8 comments

Comments

@andresluuk
Copy link

andresluuk commented Aug 30, 2018

We are having some issues to get JRebel to work with openJ9 as with a native agent bootstrap (-agentpath)

The current main question is: Is there some way to define a class into the 'java.base' module very early on; by early I mean so it can be used as a super-type to String.

Potentially something equivalent of '--patch-module', but accessible at 'Agent_OnLoad' time. I know the equivalent system properties have already been read at that time, and none of the JVM-TI or JNI spec functions allows for setting patch module paths.

When I use a plain javaagent and --patch-module then I am able to get our stuff working. Because classes from --patch-module java.base path are defined into java.base.

I got it working on my machine with a hack for createramclass.cpp~2800

I played around with hardcoded positions of javaBaseModule and unamedModuleForSystemLoader in J9JavaVM before defining a class.

e.g. Before defining one of our classes, that is suppoesd to go into java.base, I sat J9JavaVM->unamedModuleForSystemLoader=J9JavaVM->javaBaseModule in our agent and reverted if after define was done.

I know now that the pointer offset of javaBaseModule from the beginning of J9JavaVM is 18800 in my local openJ9 build.

But this has the problem that the relative locations of those modules probably changes from JVM version to JVM version.

We would need some reliable way to get the classes we need into java.base.

If possible maybe a new internal JVM property? That we could set in our native agent using the default jni APIs and that is read in createramclass.cpp~2800? to return javaBaseModule instead of unamedModuleForSystemLoader etc?

Some differences open JDK:

After the Object is loaded open JDK does not have the concept of a module so all the classes defined there will go to java.base.

@DanHeidinga
Copy link
Member

Reference to the JVMTI spec's VMStart event: https://docs.oracle.com/javase/10/docs/specs/jvmti.html#VMStart

If the capability has not been added then the VM delays posting this event until it is capable of loading classes in modules other than java.base or the VM has completed its initialization.

We'll need to check when OpenJ9 sends the event and check the RI's behaviour to see if all classes loaded before this event are loaded into java.base or not.

@andresluuk
Copy link
Author

I played around some more:
First I tried to set some system property to be checked in createramclass.cpp but (*jvmti)->SetSystemProperty does not work that early on.
By using the C command putenv(...) in Agent_OnLoad I was able to pass the parameter and it was seen in createramclass.cpp, but I was not able to change the parameter in our event ClassFileLoadHook. And adding a complex parameter with putenv that must be parsed in createramclass.cpp does not seem that good.

Finally we got a new idea for an integration. Maybe we could use the jvmti extensions mechanism?
You could add an extension callback or function that we could implement (com.ibm.DefineToJavaBaseInsteadOfUnamed etc.).
The parameter would be the full class name of the class currently being defined as a char*.
Then we could parse if this is one of our classes that should be in java.base and return true/false based on the result.
Most of the classes that we need to have in java.base are in the package com.zeroturnaround.jrebelbase, but there are also 2 classes defined by us in java.lang that need to be in java.base.

@DanHeidinga
Copy link
Member

Finally we got a new idea for an integration. Maybe we could use the jvmti extensions mechanism?

This is a great idea! Much better than trying to match undocumented behaviour of the RI.

@theresa-m
Copy link
Contributor

working on this.

@JasonFengJ9
Copy link
Member

JasonFengJ9 commented Sep 13, 2018

Note: #2839 (comment)

I wonder if the behaviour difference JRebel has seen with classes that are defined "early" being in the unnamed module on OpenJ9 and the java.base in the RI could be due to the same kind of issue. (#2751)

Please check with @hangshao0 if his WIP PR is going to cover this issue as well.

@pshipton
Copy link
Member

JRebel needs to add additional classes, #2839 won't fix this.

@andresluuk
Copy link
Author

The proposed fix to #2839 fixed our issues described in here.
We have a class transform hook that defines some extra classes. Now if we wait for a specific java.base class that is defined before the J9_RUNTIME_JAVA_BASE_MODULE_CREATED bit is set, then all the classes we define at that point will now go to java.base witch solves our problem in here.

@pshipton
Copy link
Member

Closing since #2845 resolves this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants