What I understand is that if I use:
Instrumentation#getAllLoadedClasses()
I do get a selection of all loaded classes by the target JVM. But If I do:
Class.forName("my.class.name")
This will not be the same class as the class loaded by VM. Yes, I can add this particular class as a jar in the agent MANIFEST.MF Class-Path - but that does not look the same to me as getAllLoadedClasses()
.
Could someone please confirm whether this is correct i.e. I would not be able to find a specific class using Class.forName()
when instrumenting? My objective was not to iterate over all loaded classes using getAllLoadedClasses()
- But if there is no alternative, I guess that's okay for now.
** UPDATE
What I made a mistake in writing is the Boot-Class-Path
which I have now corrected in my manifest. Using -verbose:class
logging I managed to see that my jars are being loaded as
[Opened C:\fullpath\someother.jar]
[Opened C:\fullpath\another.jar]
[Opened C:\fullpath\different.jar]
But I don't see any corresponding loading information. I tried adding a Class.forName("a.package.in.someother.jar.classname")
and got NoClassDefFoundError. As soon as I jump into the agent jar, I cannot use Class.forName()
to check if the class is loaded by the target VM. I am getting a NoClassDefFoundError.
FURTHER UPDATE
Okay I have "Fattened" the manifest to look up all classes in my WEB-INF/lib
and tomcat's lib
directory. What I can see is below:
1) When my custom class MyClass
is loaded for the first time. -verbose
shows:
[Loaded my.pkg.MyClass from file:/C:/base/webapps/ROOT/WEB-INF/lib/mypkg.jar]
2) If I try to load the class again, it is correctly showing the above order.
3) My agent jar is manifested with all classes for my tomcat lib
and my web-inf/lib
directory. And I can also confirm that the loader sees the jars correctly.
4) Now I inject the agent, and call Class.forName("my.pkg.MyClass")
from within the agent class. I get the below results.
[Loaded my.pkg.MyClass from file:/C:/base/webapps/ROOT/WEB-INF/lib/mypkg.jar]
I acknowledge that it's system class loader loding it inside my agent code as @RafaelWinterhalter pointed out in one of his answers. Is there any way I can force a "Delegation" so that the a different classloader loads the agent class and therefore, correctly redefines a class.
Any help is appreciated.
Class.forName("[...]")
finds a different class thanInstrumentation.getAllLoadedClasses()
? Is your target class not referenced from the classes that are being loaded? – AvidityClass.forName()
inside the agent even if I have added relevant jar toBoot-Class-Path
I might be wrong, but there is a fundamental gap in the instrumentation info provided on JDK page. I have raised a bug in the system for them to check. – Teetotalismhelloworld
type application. I think you might have snatched the word just out of my mind. The solution would be to force Instrumentation to use VM's context classLoader? – TeetotalismClass.forName(String)
having to return the desired class instead of just callingloadClass
on the rightClassLoader
? – NeurogramClass.forName
orloadClass()
it goes via the same route - The issue here is that agent is loaded using System class loader - I wanted to use a different classloader - java documentation doesn't say anything about allowing a different classloader to load the instrumentation agent - so i am slightly clueless to what needs to be done here. – TeetotalismClass.forName
. When you callloadClass()
on a specificClassLoader
instance, it will use that specificClassLoader
instance, regardless of the caller. – Neurogram