I understand how to use Dynamic Proxies in Java but what I don't understand is how the VM actually creates a dynamic proxy. Does it generate bytecode and load it? Or something else? Thanks.
At least for Sun's implementation, if you look at the source code of java.lang.reflect.Proxy you'll see that yes, it generates the byte code on-the-fly (using the class sun.misc.ProxyGenerator).
I suggest that you read Dynamic Proxy Classes:
The Proxy.getProxyClass method returns
the java.lang.Class object for a proxy
class given a class loader and an
array of interfaces. The proxy class
will be defined in the specified class
loader and will implement all of the
supplied interfaces. If a proxy class
for the same permutation of interfaces
has already been defined in the class
loader, then the existing proxy class
will be returned; otherwise, a proxy
class for those interfaces will be
generated dynamically and defined in
the class loader. [emphasis mine]
The proxy class is generated on-the fly(hence dynamic proxy) and loaded by the classloader. That's why if you debug applications that relies on JDK proxying you'll see bunch of classes named 'com.sun.proxy.$Proxy0'.
To test my theory you can use an example from Dynamic proxy classes along with the VM parameter -verbose:class which will tell you the loaded classes by the classloader and you shall notice among the classes loaded the com.sun.proxy.$Proxy0.
Related
When trying to inject a class which is in the java.lang namespace via java.lang.instrument.Instrumentation#appendToBootstrapClassLoaderSearch on a OpenJDK 11, nothing happens and no error is thrown. When placing the class to inject into a different package, it works as expected.
JarFile jar = new JarFile(new File("file/to/bootstrap.jar));
instrumentation.appendToBootstrapClassLoaderSearch(jar);
// throws ClassNotFoundException java/lang/Dispatcher
Class.forName("java.lang.Dispatcher", false, null);
bootstrap.jar
└─ java/lang/Dispatcher.class
The reason I want to do this is to overcome issues with some OSGi containers. They typically restrict delegation to the bootstrap class loader to only certain packages. By default that obviously always includes java.* which is why I want to put my Dispatcher class there. I'm aware of org.osgi.framework.bootdelegation but that property only gets read during initialization. That means when attaching an agent at runtime, it's already too late to override this value.
An alternative would be to instrument all known OSGi class loaders and to white-list the agent classes. But doing that for each framework and test that for each version seems less feasible.
How can I inject a custom class like java.lang.Dispatcher into the bootstrap class loader? Are there other patterns or best practices to avoid OSGi bootdelegation issues?
To provide some more context:
My idea is to only inject this one Dispatcher class into the bootstrap class loader. The dispatcher basically just holds a static Map. The rest of the agent's classes would be loaded by a dedicated URLClassLoader which is a child of the bootstrap class loader. The agent would then register MethodHandles in the dispatcher's Map so that the injected byte code can get ahold of the MethodHandles which enable accessing the agent's classes loaded in the agent class loader.
It is possible by using unsafe API. Since Java 9, the boot class loader's implementation has changed to only check a designated jmod for a known package, but the boot search path is no longer checked.
Java 11 also removed the sun.misc.Unsafe#defineClass method but the same method is still available in jdk.internal.misc.Unsafe.
You do have to open that class's module which is internal. You can either do so by using sun.misc.Unsafe which allows you to write a field value (accessible) without accessibility checks or by using Instrumentation's official API.
If you are using Byte Buddy, have a look at the ClassInjector implementations which offer implementations for all approaches.
There is an open ticket for adressing the need of Java agents to inject helper classes but until it is resolved, this is a common workaround.
If a java class loaded at runtime as a bytecode (e.g. via ASM library or other mechanism), is it on a classpath of java? I don't see it.
How to scan all annotations of classes loaded this way, if it's not on the java classpath?
I use google reflections and a custom classloader of a 3-rd party library.
Scanning for classes works as follows:
Reflections reflections = new Reflections(ClasspathHelper.forPackage("com.mypackage",
MyCustomClassLoader),
new SubTypesScanner(), new TypeAnnotationsScanner());
Set<Class<?>> myClasses = reflections.getTypesAnnotatedWith(MyAnnotation.class);
MyAnnotation - is marked as #Retention(RetentionPolicy.RUNTIME).
The above (in a class) is loaded dynamically at runtime by JVM.
As can be seen, behind the scenes, Reflections tries to get all URLs to be scanned using 2 classloaders by default static and context.
Reflection.scan()
Update: I have found an answer Can you find all classes in a package using reflection? saying that "If there are classes that get generated, or delivered remotely, you will not be able to discover those classes." But there is no proof, however.
Can please anybody give more details on this and confirm?
Dynamically instantiating classes at run time does not change the classpath that your JVM is using. What happens is that some ClassLoader class fetches bytecode from somewhere; and makes it "available" to you. But that does in no way change the "search order" for loading classes (and that is basically what the classpath is about: it only tells the JVM where and in which order to look for classes to load).
Meaning: any "loading" of a class results in some object of class java.lang.Class.
If you want to query the structure of any loaded class; you "just" need to get to the corresponding Class object. Class provides methods like getAnnotation(). It also provides methods to retrieve other objects that represent the methods and fields of the specific Class; and those objects can be queried for annotations in similar ways.
Update, regarding the updates in the question: there are situations where you don't have access to the file system where classes are coming from. You can load classes, when you know their name, but you have no way looking into the "place" where these classes live. And that basically breaks your ability to use reflection as intended.
There is no need to "prove" that, it is simply a consequence of the fact that Java allows you to load classes when you know there name, but "hides" the exact content of "where" those classes are coming from.
What is the difference between a thread's context class loader and a normal class loader?
That is, if Thread.currentThread().getContextClassLoader() and getClass().getClassLoader() return different class loader objects, which one will be used?
This does not answer the original question, but as the question is highly ranked and linked for any ContextClassLoader query, I think it is important to answer the related question of when the context class loader should be used. Short answer: never use the context class loader! But set it to getClass().getClassLoader() when you have to call a method that is missing a ClassLoader parameter.
When code from one class asks to load another class, the correct class loader to use is the same class loader as the caller class (i.e., getClass().getClassLoader()). This is the way things work 99.9% of the time because this is what the JVM does itself the first time you construct an instance of a new class, invoke a static method, or access a static field.
When you want to create a class using reflection (such as when deserializing or loading a configurable named class), the library that does the reflection should always ask the application which class loader to use, by receiving the ClassLoader as a parameter from the application. The application (which knows all the classes that need constructing) should pass it getClass().getClassLoader().
Any other way to obtain a class loader is incorrect. If a library uses hacks such as Thread.getContextClassLoader(), sun.misc.VM.latestUserDefinedLoader(), or sun.reflect.Reflection.getCallerClass() it is a bug caused by a deficiency in the API. Basically, Thread.getContextClassLoader() exists only because whoever designed the ObjectInputStream API forgot to accept the ClassLoader as a parameter, and this mistake has haunted the Java community to this day.
That said, many many JDK classes use one of a few hacks to guess some class loader to use. Some use the ContextClassLoader (which fails when you run different apps on a shared thread pool, or when you leave the ContextClassLoader null), some walk the stack (which fails when the direct caller of the class is itself a library), some use the system class loader (which is fine, as long as it is documented to only use classes in the CLASSPATH) or bootstrap class loader, and some use an unpredictable combination of the above techniques (which only makes things more confusing). This has resulted in much weeping and gnashing of teeth.
When using such an API, first, try to find an overload of the method that accepts the class loader as a parameter. If there is no sensible method, then try setting the ContextClassLoader before the API call (and resetting it afterwards):
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
// call some API that uses reflection without taking ClassLoader param
} finally {
Thread.currentThread().setContextClassLoader(originalClassLoader);
}
Each class will use its own classloader to load other classes. So if ClassA.class references ClassB.class then ClassB needs to be on the classpath of the classloader of ClassA, or its parents.
The thread context classloader is the current classloader for the current thread. An object can be created from a class in ClassLoaderC and then passed to a thread owned by ClassLoaderD. In this case the object needs to use Thread.currentThread().getContextClassLoader() directly if it wants to load resources that are not available on its own classloader.
There is an article on infoworld.com that explains the difference
=> Which ClassLoader should you use
(1)
Thread context classloaders provide a
back door around the classloading
delegation scheme.
Take JNDI for instance: its guts are
implemented by bootstrap classes in
rt.jar (starting with J2SE 1.3), but
these core JNDI classes may load JNDI
providers implemented by independent
vendors and potentially deployed in
the application's -classpath. This
scenario calls for a parent
classloader (the primordial one in
this case) to load a class visible to
one of its child classloaders (the
system one, for example). Normal J2SE
delegation does not work, and the
workaround is to make the core JNDI
classes use thread context loaders,
thus effectively "tunneling" through
the classloader hierarchy in the
direction opposite to the proper
delegation.
(2) from the same source:
This confusion will probably stay with
Java for some time. Take any J2SE API
with dynamic resource loading of any
kind and try to guess which loading
strategy it uses. Here is a sampling:
JNDI uses context classloaders
Class.getResource() and Class.forName() use the current classloader
JAXP uses context classloaders (as of J2SE 1.4)
java.util.ResourceBundle uses the caller's current classloader
URL protocol handlers specified via java.protocol.handler.pkgs system property are looked up in the bootstrap and system classloaders only
Java Serialization API uses the caller's current classloader by default
Adding to #David Roussel answer, classes may be loaded by multiple class loaders.
Lets understand how class loader works.
From javin paul blog in javarevisited :
ClassLoader follows three principles.
Delegation principle
A class is loaded in Java, when its needed. Suppose you have an application specific class called Abc.class, first request of loading this class will come to Application ClassLoader which will delegate to its parent Extension ClassLoader which further delegates to Primordial or Bootstrap class loader
Bootstrap ClassLoader is responsible for loading standard JDK class files from rt.jar and it is parent of all class loaders in Java. Bootstrap class loader don't have any parents.
Extension ClassLoader delegates class loading request to its parent, Bootstrap and if unsuccessful, loads class form jre/lib/ext directory or any other directory pointed by java.ext.dirs system property
System or Application class loader and it is responsible for loading application specific classes from CLASSPATH environment variable, -classpath or -cp command line option, Class-Path attribute of Manifest file inside JAR.
Application class loader is a child of Extension ClassLoader and its implemented by sun.misc.Launcher$AppClassLoader class.
NOTE: Except Bootstrap class loader, which is implemented in native language mostly in C, all Java class loaders are implemented using java.lang.ClassLoader.
Visibility Principle
According to visibility principle, Child ClassLoader can see class loaded by Parent ClassLoader but vice-versa is not true.
Uniqueness Principle
According to this principle a class loaded by Parent should not be loaded by Child ClassLoader again
I have a question about java ClassLoaders. I am trying to use different ClassLoaders to be able to run different versions of a JAR from within the same program.
I have heard somewhere that if you load one class using one ClassLoader all classes called (being loaded) from within that class would use the same ClassLoader. Is this correct?
If not, is there a neat way to set the context of a ClassLoader (let's say, everything being called from a specific class/library should use the same ClassLoader).
This is not a simple subject and i would advise doing more research online as no answer here will be nearly in depth enough. but, as a quick synopsis:
classes loaded via normal class references (i.e. a line of code in Class A which uses a variable of static type B) will be loaded using the same classloader as the initial class.
however, due to classloader delegation, a class may not actually be loaded by the ClassLoader from which the search originally started. example, i have Class A loaded by classloader LA with parent classloader LP. Class B is referenced by A, so the search for Class B will start with LA. however, the class bytes for B are actually found in LP, so LP loads the class and hands it to LA which returns it. ultimately, however, B is owned by LP, not LA.
with utilities which load classes via reflection (e.g. serialization, JAXB, Hibernate, etc.) or frameworks which are typically used with nested classloaders (e.g. Java EE appservers), all bets are off. typically utilities/frameworks like this load classes using the context classloader, but that is not always the case. each utility may have different priorities and fallbacks regarding which classloader is used. additionally, many have ways of explicitly providing a classloader at runtime.
as a rule of thumb, while executing code which you know is from a nested classloader (probably because you set it up), you should set the current context classloader appropriately.
I have a situation where I have a registry class to which certain classes have to register themselves for the system. Since I'm writing an API I can't necessarily know which these classes are before runtime, so my solution is using a static block within each class for it to register itself.
The problem is of course that the static block isn't run until each class is initialized, and because there are no explicit references to each individual class, they never are initialized. Catch-22.
So, is there any way or annotation to make sure that a class is initialized at startup without referring to it explicitly?
Spring for instance, does this using the #Component annotation, or any if its subclasses, to scan for annotated classes at runtime. You could use spring for this, implement such functionality for yourself, or use a dedicated library such as scannotation.
If you decide to look into spring, you can use the bean ClassPathScanningCandidateComponentProvider standalone to scan for classes with a given annotation.
If you're not running in some sort of container environment (e.g. using OSGI,Spring,Guice etc..), there's no general way yet without making it explicit. You can take the approach of JDBC, in which the user of a particular JDBC driver library have to make sure the driver is initialized before use,
i.e. someone have to run e.g.
Class.forName("org.postgresql.Driver"); , which will load the org.postgresql.Driver class. In that class you can have a static initializer which also loads/registers all the other classes you need.