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