This discussion is archived
3 Replies Latest reply: Mar 17, 2011 2:03 PM by jschellSomeoneStoleMyAlias RSS

Reinitialize Java Class

847865 Newbie
Currently Being Moderated
We are working on a JVMTI Java Agent, that is used to instrument java class files. A small part of it is (obviously) native c++ code, but the larger part is Java code, which is loaded over the network and called from the native agent code.
We use a code coverage tool to collect test coverage for the java part, which does source code instrumentation.

Now when our agent starts, some classes get initialized, specifically java.lang.ref.Reference, which starts a Thread. Our Agent instruments the Thread start method with custom java code, which is instrumented by the code coverage tool.
The coverage tool puts some static inner classes with static initializers in our java agent code, so this gets executed as a consequence of java.lang.ref.Reference getting initialized.

The Problem is, that at this time (when java.lang.ref.Reference gets initialized), some basic functionality of the JVM is not in place yet. Specifically, the code coverage tools initializer wants to access System.getProperty(String name), but System.props is still null, so the call results in a NullPointerException.
This leads to the static inner class of the code coverage tool is being left uninitialized, the class is in state initialization_error, the result is NoClassDefFoundError. Each follow up access to this class results in a NoClassDefFoundError.

A psuedo callstack of the static initialization of Reference would look like this:
Reference.<clinit>
  ...
     Thread.start()
        try {
            ourAgentHelper.tagThreadStart()
               codeCoverageInnerClass.Recorder.record()
                  codeCoverageInnerClass.<clinit>  ----> NoClassDefFoundError
                     ...
                        Recorder=codeCoverageTools.createRecorder()
                           System.getProperty("file.separator")   ----->  NullPointerException
        } catch (LinkageError e) 
        {}
The try-catch and everything beneath it is inserted by our agent.

That means, that Thread.start works ok, since we catch and ignore LinkageError. Reference gets initialized ok.
There are 2 problems for us:
* codeCoverageInnerClass never gets initialized, so no Coverage is ever recorded (for ourAgentHelper)
* the code in ourAgentHelper.tagThreadStart() never gets executed, since the first thing that happens is a NoClassDefFoundError (which we cannot catch, since the coverage tool instruments its calls before our first statement in the method).

What i want is to have the JVM reinitialize the codeCoverageInnerClass at a time when everything is in place.
My intention now is to ignore this initial initialization error, and wait until VM_Start and then reset the ClassState of the class in question to "linked". This way i hope that the JVM will try to initialize the class again in follow up accesses to the class.

Does anyone have an idea, if this can be done from the JVMTI Agent, and give me some suggestions how this could be done?

Edited by: Ron on Mar 17, 2011 4:16 AM

Edited by: Ron on Mar 17, 2011 4:32 AM
  • 1. Re: Reinitialize Java Class
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Does anyone have an idea, if this can be done from the JVMTI Agent, and give me some suggestions how this could be done?
    My idea would be that no this cannot be done.

    A java class, any java class, remains in memory until the class loader that loaded it can be collected.

    You are not mucking about with a normal java class but instead with the classes the form the VM itself and likely those that are essential for the VM itself to run. So reloading it is likely a matter of reloading the VM. And that isn't going to help you.

    Mucking around with these core classes would be something of a last resort but presuming that there is absolutely no other solution then your only solution is to insert more JNI where the JNI minimizes what it relies on. So if you want a property value then you write C code and only C code to go get the value and return it as a String.
  • 2. Re: Reinitialize Java Class
    847865 Newbie
    Currently Being Moderated
    Actually I do not want to reinitialize a JDK class, but the static Inner Class that was injected by the code coverage tool into our classes. That is the one that does not get initialized.
    I updated the initial post and supplied a pseudo callstack to make clear what happens.
  • 3. Re: Reinitialize Java Class
    jschellSomeoneStoleMyAlias Expert
    Currently Being Moderated
    Ron wrote:
    Actually I do not want to reinitialize a JDK class, but the static Inner Class that was injected by the code coverage tool into our classes. That is the one that does not get initialized.
    I updated the initial post and supplied a pseudo callstack to make clear what happens.
    That doesn't change what I said.

    A standard hot load mechanism is as follows
    Proxy class -> custom class loader -> real class

    You can use the proxy class and via that mechanism to reload the real class.
    However nothing changes the fact that when the thread starts it will still not have access to the information. It will only exist later. If that is ok then you can use the proxy mechanism.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points