Instrument Java bytecode without agent - bytecode

Is it possible to dynamically instrument Java bytecode without a Java agent? I have instrumented bytecode using a Java agent before, doing something akin to this:
ClassFileTransformer myTransformer = new Transformer();
instrument.addTransformer(myTransformer, true);
instrument.retransformClasses(classInstance);
instrument.removeTransformer(myTransformer);
But is this possible without the use of a Java agent? What I would like to do is call a method which will do my instrumentation at any given time after the JVM is running, just without the use of an agent.

The only ways to perform byte code transformation without an instance of an Instrumentation implementation would be
Custom class loaders which can change the bytes before calling defineClass (which is limited to classes loaded through that loader)
Calling MethodHandles.Lookup.defineClass with modified bytes even before the class has been loaded, which works on the widespread JVMs with lazy loading, but is limited to your own module or modules opened to your module
Neither approach can change already loaded classes. That requires the Instrumentation reference and the only place where a JVM ever hands out such reference, are the initialization methods of Java Agents. So to use it, a Java Agent is unavoidable, even if it may be just a stub storing the reference, for use by your application code.
Note that starting with Java 9, there is the Launcher-Agent-Class manifest attribute for jar files that can specify the class of a Java Agent to start before the class specified with the Main-Class is launched. That way, you can easily have your Agent collaborating with your application code in your JVM, without the need for any additional command line options. The Agent can be as simple as having an agentmain method in your main class storing the Instrumentation reference in a static variable.
See the java.lang.instrument package documentation…
Getting hands on an Instrumentation instance when the JVM has not been started with Agents is trickier. It must support launching Agents after startup in general, e.g. via the Attach API. This answer demonstrates at its end such a self-attach to get hands on the Instrumentation. When you have the necessary manifest attribute in your application jar file, you could even use that as agent jar and omit the creation of a temporary stub file.
However, recent JVMs forbid self-attaching unless -Djdk.attach.allowAttachSelf=true has been specified at startup, but I suppose, taking additional steps at startup time, is precisely what you don’t want to do. One way to circumvent this, is to use another process. All this process has to to, is to attach to your original process and tell the JVM to start the Agent. Then, it may already terminate and everything else works the same way as before the introduction of this restriction.
As mentioned in this comment, Byte-Buddy has already implemented those necessary steps and the stripped-down Byte-Buddy-Agent contains that logic only, so you can use it to build your own logic atop it.

Related

Spring Boot 3 Build vs Runtime Initialization Hints

I am working on creating an internal library/starter for my team that will add support for creating native images, providing all of the hints that our currently unsupported dependencies will need. I really like providing the metadata via code (using RuntimeHintsRegistrar), but there are also certain classes that need to be initialized at build time for whatever reason.
Right now I'm passing the --initialize-at-build-time and the classes to the Spring Boot Maven Plugin via the BP_NATIVE_IMAGE_BUILD_ARGUMENTS, but ideally I'd like to avoid each consuming app having to include this in their own POM's plugin configuration.
I also understand that I can go more low-level and provide the argument inside of the META-INF/native-image directory in a native-image.properties file, but I'm not sure whether that will play nice with the Spring-provided RuntimeHintsRegistrar effectively creating that underneath the covers.
What is the best way to tell native-image the classes that should be initialized at build time without each consuming app having to pass it in their own POM? Also, if I use the GraalVM tracing agent to generate hints, will those hints play nicely with the ones that RuntimeHintsRegistrar generates?
Thanks in advance!

Spring AOP with AspectJ - Load time weaving doubts

Reading the Spring AOP documentation (link), I'm having a hard time (maybe also because english is not my native language) understanding these paragraphs.
First, I read
Further, in certain environments, this support enables load-time
weaving without making any modifications to the application server’s
launch script that is needed to add
-javaagent:path/to/aspectjweaver.jar or (as we describe later in
this section)
-javaagent:path/to/org.springframework.instrument-{version}.jar
(previously named spring-agent.jar).
And
Developers modify one or more files that form the application context
to enable load-time weaving
Which files? #Aspect classes and aop.xml files?
Then, when describing an example in the same sub-chapter, they say
We have one last thing to do. The introduction to this section did say
that one could switch on LTW selectively on a per-ClassLoader basis
with Spring, and this is true. However, for this example, we use a
Java agent (supplied with Spring) to switch on the LTW. We use the
following command to run the Main class shown earlier:
And they apply a Java Agent to the JVM.
-javaagent:C:/projects/foo/lib/global/spring-instrument.jar
Now I have a couple of doubts.
If I #EnableLoadTimeWeaving, do I need the spring-instrument Jar file as Java Agent?
I suppose the answer is yes, because we need to add bytecode to the class file before loading it. But a confirmation would be much appreciated.
The Jar naming is a little ambiguos, first they mention spring-agent.jar, then they use org.springframework.instrument-{version}.jar, and then spring-instrument.jar.
Are we always talking about the same Jar file?
I see from another question you asked that you are using Spring Boot and running a fat jar. In this case you don't need #EnableLoadTimeWeaving or spring-instrument (formerly known as spring-agent). Just ignore them if you are not running in an appserver for which you don't control the agent path.
I opened an issue for you about the confusion in the docs: https://github.com/spring-projects/spring-framework/issues/22429.

Lazy activation of Eclipse plugins

I would like to know what is "Activate this plug-in when one of its classes is loaded" check-box in Eclipse manifest editor useful for.
I thought Eclipse always use "lazy initialization" approach. Does have this option a relation to the BundleActivator class of the plugin? is initialization something different to activation?
Here is a similar question, but I don't understand it entirely.
Ticking the box causes the following header to be set in the manifest:
Bundle-ActivationPolicy: lazy
I'll start with how "pure" OSGi deals with this. IF the bundle is started with the START_ACTIVATION_POLICY flag then the bundle enters the STARTING state but the activator's start() method is not invoked and a ClassLoader is not allocated for the bundle. The bundle stays in STARTING until, for whatever reason, a class needs to be loaded from the bundle. At that point a ClassLoader is allocated and the activator (if any) is instantiated and its start() method is invoked before the requested class is loaded.
However Eclipse layers additional semantics on the top. As background, Eclipse always tries to avoid starting bundles in order to keep its start-up time minimal. A very small core set of bundles is started by default (the list is in configuration/config.ini) and one of these is called the p2 "simpleconfigurator". The simpleconfigurator looks for bundles that have the Bundle-ActivationPolicy:lazy header and it starts them with the START_ACTIVATION_POLICY flag... therefore these bundles will be "lazily" started as described above.
The important point is that all other bundles that do not contain the header will not be started at all under Eclipse. They will stay in RESOLVED state, their activators will not be invoked, and if they contain any Declarative Services component they will not be loaded. This is because Declarative Services only ever looks at bundles that are in ACTIVE or STARTING state.
Therefore the main reason to use the header is if we want to write a bundle containing Declarative Services components that need to work under Eclipse.
In other environments there is no need to use the header. Most normal OSGi apps simply start all bundles, rather than trying to selectively start a subset of bundles. Note that this doesn't mean OSGi apps don't worry about lazy loading! Declarative Services already supports lazy loading without messing around with bundle class loading triggers. In my opinion Eclipse gets this wrong and has added unnecessary complexity to the bundle lifecycle. Nevertheless if you are running in Eclipse then you have no choice but to understand and work with its limitation.

ClassLoader finds Resource only in specific Threads

I am struggling with a situation in which a ClassLoader is trying to resolve a resource, which only works under certain conditions.
The use-case is as follows: I am using IBM Rational Functional Tester in combination with JBehave for automated acceptance tests. JBehave specifies the tests as plain text story files. These story files can refer to other story files, so called "Given Stories". JBehave uses the ExecutorService to execute stories potentially multi-threaded. While JBehave has no problems to load the text files (with ClassLoader.getResourceAsStream), it fails finding the same files in the thread launched from ExecutorService.
The ClassLoader in action is the ContextFinder. When debugging the application, and suspending both threads, the "main thread" that originally started JBehave and the "story thread" launched from the executor service to run the story file, I can identify that the instance of the classloader is the same. Also the instances of the parents, etc.
But a call to
Thread.currentThread().getContextClassLoader().getResource("HelloWorld.story")
works perfectly in the main thread, and fails for the story thread and returns null.
Judging from the source code of the ContextFinder, it seems like it does little else then gathering all the ClassLoaders for the classes on the stack. So I tried this:
SomeClass.class.getClass().getClassLoader().getResource("HelloWorld.story")
... with the same result.
This is too strange for me. Any pointer for debugging or reasing why this behavior is showing is appreciated!
The thread context classloader (TCCL) is basically undefined in OSGi. You should avoid using it.
As an extension to standard OSGi, Equinox does supply this thing called the ContextFinder, which performs stack inspection to try to find the topmost OSGi bundle classloader in the call stack. However you get almost no control, and the result can be quite unexpected as you have seen. Of course since this is an Equinox-specific extension, any code that relies on ContextFinder working properly will fail on all other OSGi Frameworks.
So, rather than wasting time trying to debug this, it's better just not to use the TCCL at all. If you want to load a resource relative to a specific class, then do it from the literal class object, e.g.:
MyClass.class.getResource("HelloWorld.story");
UPDATE:
I noticed this in your original question: SomeClass.class.getClass(). The result of this will be the class-object of java.lang.Class itself. Calling getClassLoader() on that will always return the JVM boot class loader.... probably not what you intended!

Can I create a transient configuration in OSGi using the ConfigAdmin?

I'd like to create a Configuration object in OSGi, but one that won't be persisted, so it won't be there when the framework is restarted. Similar to START_TRANSIENT for bundles.
Some background: I've got an OSGi (Felix) based client side application, deployed over OBR. The configuration object I'm talking about effectively boots the application. That works fine, but sometimes the content has changed while the context was stopped. In that case, it boots the application as OSGi revives all bundles and adds all configuration options. Then I inject the correct configuration, the application stops and then restarts again.
So it does actually work, but the app starts twice, and I can't get access to the framework before it reconstructs its old state.
Any ideas?
As BJ said there is no standard support for this in the Configuration Admin spec.
However the Felix implementation supports two features which may help you. First, you can set the felix.cm.dir property which configures where the configadmin saves its internal state (which by default will be somewhere under the Framework storage directory). You could set this to a location that you control and then simply wipe it every time you start OSGi (you could also wipe out the entire OSGi Framework storage directory on every start... some people do this but it has wider consequences that what you asked for).
Second, if you need a bit more control, Felix ConfigAdmin supports customising its persistence with a PersistenceManager service. You could probably implement this and return empty/doesn't-exist for the particular pids that you want to control.
The OSGi Config Admin spec does not support this. I also do not know of a non-standard means either for any of the CM impls I am familiar with.
Ok, what I did in the end was the following:
I created a special really small 'boot' bundle, which I do not provision from OBR, instead, I install it from the classpath.
That bundle controls the configuration, and I use START_TRANSIENT the moment I really want to load that configuration.
Not exactly pretty, it gets the job done. I do think transient configuration would make sense to have in OSGi.

Resources