On Jan 2, 2007, at 3:38 PM, David Blevins wrote:

Excellent stuff, Dain!

On Dec 29, 2006, at 6:08 PM, Dain Sundstrom wrote:

I just committed the code to enable runtime enhancement of JPA entities. The code makes use of the java instrumentation APIs[1] to hook all class loading. The gives us direct access to hook all class loading in the vm and to modify the java byte code for the class before it is loaded into memory. I have a few notes on the the instrumentation APIs so hopefully others will be able to support this code :)

* To use the instrumentation API, our java agent *must* be specified on the command line. I have added this to the standalone startup shell scripts. Without the agent we cannot enhance classes and pre-enhancement must be used [2]. Embedded servers (Tomcat and JUnit) must load the java agent or pre-enhance java -javaagent:$OPENEJB_JAVAAGENT_JAR -jar $OPENEJB_CORE_JAR start

Do you think you'll be able to find a naughty way to install an agent after boot?

I doubt it. I don't think the vm initializes the instrumentation system, unless there is an agent specified on the command line. I hope to spend some time looking at the VM source to see if there is a secret late instrumentation hook but I doubt it.

* It is critical that application classes not be loaded before the Assembler. Code that runs before the Assembler, such as the Verifier, should use the TemporaryClassLoader. The TemporaryClassLoader loads all locally (even those found in parent class loaders), which means it doesn't pollute the parent class loader. (I forked this code from OpenJPA. thanks guys)

That's cool. I suppose this supercedes the patent-pending Alan Cabrera TempCodebase?

I think so, but I haven't looked at the TempCode base enough to know if it covers all the use cases.

* A javaagent works much like an executable jar in that you specify a Premain-Class and Boot-Class-Path in the javaagent jar manifest. One big problem is that the premain class can not be debugged (at least in IntelliJ). It appears that the premain is executed before the debugger starts.

Guess that puts a damper on using it to do other naughty things like use it as a container system boot hook. Though still possible.

We'll I'd use the premain to install a class file transformer that adds a static initializer to the real main class which causes the container to initialize. That way your initialization code executes as part of the main. This is a bit tricky as you need to know the name of the main class, but there are only few things we integrate with.

* Once you have a javaagent it is very easy to use ASM to modify a class. There is an example ClassFileTransformer in the JpaTest that adds a new field to a class at runtime[3].

That is all I can think of now :)

So are we using this in our test suite now or are we still pre- enhancing?

We are using runtime enhancement in the tests now.

-dain

Reply via email to