I am currently reading Class loader and their hierarchy functionality.
If I call below code -
ClassA a= Class.forName("com.test.ClassA")
As per my understanding,now it will be initialized and loaded in memory with help of Application Class loader.
I have below questions:
What will happen if I call again call the above code? Will there be new instance created in memory for 'ClassA' or will it return the same loaded class reference?
If yes, as per this post of javarevisited,"By using separate ClassLoader you can also loads same class from multiple sources and they will be treated as different class in JVM"
What will be use of it?
You will get the same class. Just test it. Load it a second time and check if a1 == a2.
The most frequent usage of this feature is probably in app servers: you can deploy several web applications in a single server, and all can use the same classes. But they shouldn't share static variables. And if one uses class Foo from library 1.0, and the other one uses class Foo from library 2.0, there should be no problem. Hence the need to load the same class with different class loaders.
New instance is created only if you call:
ClassA inst = new ClassA();
If you call Class.forName, the class definition (metadata and bytecode) is loaded into JVM, into special section of managed memory called HEAP. Usually, the applications use this function to preload class into JVM, so that later on there is no latency when application needs it.
The use is hotdeploy for example. You're debugging java web server. You find a mistake, and just want to change (reload) one class, not the whole application. Important point here is also "Different Class Loaders". That means that libraries in java can be loaded from different sources: jar, war (archives), from database, from network. Compare this to COM model of Windows, where library must be in same folder or /system32/ folder.
Related
My situation is as follows:
I have two scala applications, app 1 and app 2. Both use sbt. I ran "publishLocal" in the sbt shell for App 2, and then made App 2 a library in app 1 (I added it as a library dependency in build.sbt). Within app 2, I have a function, foo, the line
Class.forName(<CLASS NAME>)
I want to pass a class path for class bar from app 1 to the foo function in app 2, so that I can get use an instance of the bar class in the foo function. However, when I try this, I get a ClassNotFoundException. I have isolated this problem to the fact that the code which calls "Class.forName" is using the bootstrap class loader, and the bar class is loaded using some other class loader. I cannot change the code in app 2, but I can change the code in app 1 - is there a way that I can somehow specify that bar should be loaded with the bootstrap class loader, or in some other way make it discoverable for app 2 in the foo function?
If I understood correctly, you have a setup like:
app1 (= Application)
Bar.class
app2 (= Lib)
class with function foo(...) that wants to use Bar.class
where they both were loaded by different classloaders and you want to lookup Bar.class inside the foo function in app2.
Does the app2 setup have any classpath dependencies on app1 so that classes of app1 are actually loadable by app2? If not then chances are low that you are able to use that class.
Let's recap what is happening here. Classloaders usually work on a delegation model. Classloaders respecting the delegation model will first check their loacal cache whether the class was already loaded by that classloader before and if not ask their parents whether they know the definition of that class. Only if none of the ancestors knew about that class before the actual bytes defining the class are loaded by the class loader that initiated the lookup chain. In order to load the bytes of that class definition, the classloader will usually check its classpath if there is any JAR archive or directory mentioned that contains the definition. If multiple sources are present that provide the class definition, the first one found will be loaded which could lead to shadowing issues down the road if multiple versions of the same class linger around in different archives/directories.
So, if the classpaths of these two applications (or application and library) are setup in a way that they don't have access to the other's Java archive (JAR) they won't be able to even load and lookup the class definitions of the other application. Probably the best advice to give is to extract common classes into an own library, i.e. commons or base, and add this library to the classpath of both applications so that the application loader of the respective application/library is able to load the class definitions of shared classes.
Note however, the same class definition, i.e. for class Bar, loaded by two different classloaders will result in CL1.Bar != CL2.Bar as the classloader who loaded that class definition is a part of that class, meaning that event though the byte representation of the class in both classloaders is identical, the actual Class<Bar> object you obtain is different. This quickly may get an issue if you think about returning the class definition loaded in foo(...) and compare it in app1 with some local Bar.class and wonder why a check of barObject.getClass() instanceof Bar (or the like) is failing, assuming barObject is the product returned by app2.foo() and Bar being app1.Bar.class.
In regards to Class.forName(...) using the bootstrap classloader: Class has actually two forName(...) methods present. One only taking the fully qualified class name to return the class object for, which uses the classloader that actually loaded that respective class, which is almost always the boostrap classloader. The second one has the following signature:
Class<?> forName(String className, boolean initialize, Classloader loader) where you can specify the classloader it should use to lookup and load the class definition with. So, as long as you at least have a reference to a class loaded by the other class loader present you can obtain the reference to that classloader via otherAppObject.getClass().getClassLoader().
Further note that if your applications use Java's module capabilities, you might need to open up the modules so that classloaders are actually able to load the definitions for these classes at all.
... is there a way that I can somehow specify that bar should be loaded with the bootstrap class loader, or in some other way make it discoverable for app 2 in the foo function?
I don't know about sbt TBH, but usually adding the location of the JAR archive of app1 to the classpath of app2 should be enough to allow the classloader of app2 to load, define and return the class definition of classes used in app1. As mentioned, extracting common classes used by both to a library that is added to both applications classpath is probably the recommended way.
Is it possible to load multiple versions of the same class into the JVM. I have a version of the class "XYZ" loaded in the main thread and I have multiple children threads doing some work. I want to load different versions of class "XYZ" in to children threads.
Is this doable? I was thinking of creating a new context class loader for each of the children threads and use this context class loader to load a different version of the class. For now I am using URLClassLoader for context class loaders but that does not seem to work. Do I have to create a custom class loader to the do the job?
Here is the code I have so far.
final Thread builderThread = new Thread("Child Thread " + buildToken) {
#Override
public void run() {
futureTask.run();
}
};
try {
URL url = new URL("file:///path to the jar file");
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
classLoader.loadClass("XYZ");
builderThread.setContextClassLoader(classLoader);
}
The reason why I want to have different versions of the class is because I want to have different values for the static fields in the class "XYZ".
Yes, it is possible, and you're on the right track with URLClassLoader. The scope of your classloaders will be determined by the scope you want the static fields to have. For example, if each task or thread should have its own copy of those fields, then each task or thread must have its own classloader.
There are a couple other issues to be aware of. First, the class you want to load multiple times must not be found on the system classpath. This is because classloaders exist in a hierarchy, and delegate to their parent before attempting to load a class themselves. If the system classloader finds the class, it will load it only once, and other classloaders will use the class loaded by the system classloader.
Second, the JVM will treat each loading of the class as a distinct class, despite the fact that they're all identical. This means that instances of the dynamically loaded class must be confined to the scope of their classloader. If each task has its own classloader, then instances cannot be passed between tasks. And obviously you cannot publish instances to the rest of the app, because the rest of the app uses the system classloader, which must not know about the class. (You can get around this somewhat if the dynamically loaded class has a superclass or superinterface that the system classloader does know about. Then you can publish the instance as that type.)
The reason why I want to have different versions of the class is because I want to have different values for the static fields in the class "XYZ".
This really seems like a hack to me. Do you really have no other way to inject different values into this class?
How about passing some sort of Context instance for each thread and convert your class to use the settings from the Context instead of from static fields. You could also use a ThreadLocal so each thread would get the static field information from there instead.
Loading different versions of the class is going to be extremely hard (if not impossible) to debug. The only time I've ever heard of folks using multiple class loaders is when you have security concerns (often in a web server environment) and there is a deliberate point to having separation between the web classes and the outer admin classes.
I'm developing a simple Plugin System and I basically want to control which classloader loads a class on a new instruction.
For instance I have a jar with my main program, and I distribute a class Foo.class in a extra packaged jar called Bar.jar.
I see three different possibilities to include the jar in my main program:
package Bar.jar with my main jar to include it in the classpath. This is obviously not feasible for a plugin system
Load the class Foo with an URL ClassLoader pointing to the jar. This would be too unfamiliar with the default java programmer to load classes manually via its name
Set a custom Classloader as the System-classloader via the -Djava.system.class.loader argument. But I dont really want to force the user to start his application with extra arguments.
Is there another way? Maybe something to register a Custom classloader for specific classes? or change the Classloader new uses at Runtime? Setting the ContextClassLoader of the Thread does not work.
When you load a class, the classes it refers to use the same class loader as it. This means to control the class loader used implicitly, you can to use a different class loader for the one which starts it all. e.g. Your first Runnable.
class A {
B b = new B();
The new B will chose the ClassLoader used for A (or a parent)
Setting the context class loader works for dynamic lookups like Class.forName(name); is the same as Class.forName(Thread.currentThread().getContextClassLoader(), name);
Once a class is loaded it will always use the same classes it depends on. It's not possible to swap different classes based on say a thread context. This means a class with a very specific classloader can use classes which are more generally used (e.g. as the general class is from a parent), however a more general used class cannot use a more specific class loader it is not aware of. i.e. ClassLoaders are not aware of their children.
One reason for this is that threads share memory. This means you can't say that when A creates a new B in one thread it will be different to another thread as the A instance could be accessed by either thread.
I have an application that needs the ability to update parts of itself (one class at a time) without stopping and restarting. With the JavaCompiler API, it is straightforward to generate modified class source code, recompile, load, and instantiate a class. I can do this all in memory (no files read from disk or net).
The application will never instantiate more than one object of such a class. There will only be two or three references to that object. When the modified class is loaded and instantiated, all those references will be changed to the new object. I can also probably guarantee that no method in the affected class is running in another thread while loading the modified class.
My question is this: will my class loader have problems loading a modified class with the same name as a class it previously loaded?
If I do not explicitly implement a cache of loaded classes in the class loader, would that avoid problems? Or could delegation to a parent class loader still cause a problem?
I hope to use a single instance of my class loader, but if necessary, I could instantiate a new one each time I update a class.
Note: I looked at OSGI and it seems to be quite a bit more than I need.
There's a useful example on this at http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
We do quite a bit of dynamic class reloading ourselves (using Groovy for compilations). Note if you've got class dependencies then you may need recompile these dependencies on reload. In dev stacks we keep a track of these dependencies and then recompile whenever dependencies become stale. In production stacks we opted for a non-reloading ClassLoader and create a new ClassLoader when ever anything changes. So you can do it either way.
BTW - you might find the GroovyScriptEngine at http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.groovy/groovy-all/1.8.5/groovy/util/GroovyScriptEngine.java#GroovyScriptEngine very interesting if you want to dig around how they do it.
Okay, it should work: when you load the new class, it will replace the class name in the appropriate tables, and the memory should be GC'd. That said, I'd give it a strenuous test with a real short program that compiles a nontrivial class and replaces it, say 10,000 times.
On different sites , Dynamic class loading is given as one of the reason of permgen problem.
As per my understanding , Dynamic class loading is loading the class as and when it is required.Alonwith that if Class A is loaded and it is referring another class B , it will also be loaded along with that. This is Dynamic class loading. Right? If yes, this is essential and inbuilt feature of JVM. What we can do about it?
Or my understanding is wrong here. when we say Dynamic class loading , are we reffering to custom class loaders here?
My last question related to above is, Class is loaded once by customer loader. So when we do hotdeployment on application server, how appserver loads the new version of class. Does it use different class loader here?
No, dynamic class loading refers to loading classes during runtime that are unknown at compile time, e.g., via Class.forName, or reflection (1, 2).