-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add premain for static agent support #8988
base: master
Are you sure you want to change the base?
Conversation
|
||
private static final String PREMAIN_OPTION_PREFIX = "-XX-premain:"; | ||
|
||
class PremainMethod { |
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 could be a record, right?
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.
Should be static
if it is a class.
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 could be a record, right?
Yes, in my current implementation it's recorded by native-image-agent.
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 could be a record, right?
Yes, in my current implementation it's recorded by native-image-agent.
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.
When I say a record
I mean a java record.
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 see. Yes, this is a java record. I have fixed it.
// premain method must be static | ||
premainMethod.method.invoke(null, args); | ||
} catch (Throwable t) { | ||
VMError.shouldNotReachHere("Fail to execute " + premainMethod.className + ".premain", t); |
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 should be a user-facing error, right? User code can throw, so I don't see this as something that is a VMError
. What does the JVM do in this case?
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.
In JVM, if the premain
method fails, the JVM starting process shall be terminated. See https://github.com/openjdk/jdk21u/blob/2971cb5769121b47ac8c8db1078d67680a19341f/src/java.instrument/share/native/libinstrument/InvocationAdapter.c#L623-L629
I use VMError
because it's a fatal error during VM starts up. But the cause is indeed an user error.
* registered premain method's second parameter. At native image runtime, no actual | ||
* instrumentation work can do. So all the methods here are empty. | ||
*/ | ||
public static class SVMRuntimeInstrumentImpl implements Instrumentation { |
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.
Maybe NativeImageNoOpRuntimeInstrumentation
? SVM is an internal name which we should not use. I also feel we should mention it is a noop and that it happens at runtime.
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.
fixed
} | ||
preMainSupport.registerPremainMethod(premainClass, premain, args.toArray(new Object[0])); | ||
} catch (ClassNotFoundException e) { | ||
VMError.shouldNotReachHere("Can't register agent premain method, because the declaring class " + premainClass + " is not found", e); |
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 a UserError
as the user can make a mistake. We should also add a sentence on how to recover from that mistake to the error message.
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.
fixed
* <ul> | ||
* <li>Isolate code by checking current runtime. For example: <code> | ||
* <pre> | ||
* String vm = System.getProperty("java.vm.name"); |
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 should guide the users to use the properties from ImageInfo. Then they can see if the agent is applied at build time or at runtime. We also need to make sure that this property is set before premain is called for the Native Image builder.
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.
Fixed. This property can be obtained in premain
.
* Keep premain options and return the rest args as main args. | ||
* The premain options format: | ||
* <br> | ||
* -XX-premain:[full.qualified.premain.class]:[premain options] |
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 am not sure if this should be our final format for the flag. I think we can use it until we complete the feature and decide what is the user interface in the end.
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.
Agreed. I added a //todo
for future changing.
|
||
public static class Options { | ||
@Option(help = "Specify premain-class list. Multiple classes are separated by comma, and order matters.")// | ||
public static final HostedOptionKey<LocatableMultiOptionValue.Strings> PremainClasses = new HostedOptionKey<>(null); |
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 also an internal option. In the end we should probably pick the premain
functions from the agent JARs.
@Override | ||
public void afterRegistration(AfterRegistrationAccess access) { | ||
FeatureImpl.AfterRegistrationAccessImpl a = (FeatureImpl.AfterRegistrationAccessImpl) access; | ||
cl = a.getImageClassLoader().getClassLoader(); |
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'm not sure this is still required, but I had to provide an agent JAR twice as -J-javaagent
and -cp
for NI build configurations in agent JARs to be picked up by the NI builder. So just checking, users can provide an agent JAR only once as -J-javaagent
for their premain classes to be registered?
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.
In this PR, we are not automatically picking agent from -cp
or -J-javaagent
. It will be handled in the following PRs. But I'm sure user doesn't need to provide agent jar multiple times.
8e2bd2f
to
c9d5652
Compare
} | ||
preMainSupport.registerPremainMethod(premainClass, premain, args.toArray(new Object[0])); | ||
} catch (ClassNotFoundException e) { | ||
UserError.abort(e,"Can't register agent premain method, because the given class %s is not found. Please check your -H:%s setting.", premainClass, Options.PremainClasses.getName()); |
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.
It is better to use SubstrateOptionsParser.commandArgument
to print the option name. This keeps the correct behavior when options become public or change the type.
To keep this feature working as expected we need to add a few tests into: The tests can be executed from similarly to the tests for class initialization. |
c9d5652
to
538ad3f
Compare
I have added a test task agenttest. It now only checks the |
5671706
to
510b031
Compare
Java agent always has a premain method to initialize the agent. SVM needs the premain as well to support agent in native image. At compile time, -H:PremainClasses= option is used to set the premain classes. At runtime, premain runtime options are set along with main class' arguments in the format of -XX-premain:[class]:[options]
510b031
to
bc9e8ad
Compare
Java agent always has a premain method to initialize the agent. SVM needs the premain as well to support agent in native image.
At compile time, -H:PremainClasses= option is used to set the premain classes.
At runtime, premain runtime options are set along with main class' arguments in the format of -XX-premain:[class]:[options]
This PR is part of #8077