开发者

Reinitializing Java Class

开发者 https://www.devze.com 2023-02-17 02:34 出处:网络
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

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开发者_JS百科 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.

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?


From your description, I get the feeling that your code is too tightly coupled. What you really want is to have an initialized Java VM before you start your tests.

So instead of messing with native code and an agent, I suggest to split the code into three classes:

  • The Java code in an abstract base class
  • A class which extends the base class and implements the abstract methods with the native C++ code. Ideally, this class should not contain any Java code except for native method declarations.
  • A mockup class for tests which defines the same methods with empty bodies (or ones that just return null).

For the tests, instantiate the mock-up class. Override the methods that you need for the test so you can return mock data objects which the code under test needs (see mockito for some example about mock-up testing)

Alternatively, test the Java loading code in a test case. In all other tests, add the class to your classpath and just instantiate it as usual.


A RetransformClasses after VM_Start will generate a new class load hook for Reference allowing you to do your instrumentation in a safe VM phase... Either just Retransform Reference or getLoadedClasses and Retransform them all.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号