Visibility Principle in JVM Class Loader - java

What is the significance of Visibility principle in class loader of JVM? I understand the uniqueness principle that is handled by delegation model but could not decode the benefit of the Visibility principle or why would this principle was introduced in first place?

The child class loaders NEED to be aware of the parent class loaders.
The parent class loaders DON'T NEED to be aware of the child class loaders.
Why? Because of the class dependencies(inheritance, composition, etc).
Classes from the Application Classloader - those defined by the user - could use classes from the Extension or Bootstrap Classloader. But not the other way around.
Similarly, classes from the Extension Classloader use classes from the Bootstrap Classloader. Classes from Bootstrap can't use classes from the extension - if they did, they would be included in the Bootstrap. Classes from the Application Classloader didn't even exist at the time the classes in the Bootstrap were written.
Correctness benefit: Trying to load an Application Classloader class from the Bootstrap classloader would result in a circular dependency.
Optimization benefit(minor): I would imagine this delegation model to lend itself to a linked list. A double-linked list is more expensive.

Related

Which Class Loader should I use?

JNDI use Thread context class loader.
Because its guts are implemented by bootstrap classes in rt.jar
but core JNDI classes may load JNDI providers implemented by independent vendors and potentially deployed in the application's -classpath.
Father class loader can not use child class loader to load class.
Question :
As we all known parent delegation model is a important feature,
Why not using system class loader everywhere? Child class loader can use father class loader to load class.
I am not totally sure I understand your question.
Especially in JEE runtime environments the Context Classloader of your current thread is you best choice.
Essentially it all boils down to the hierachy (which may even be inverted or use something like OSGI somewhere) and the missing knowledge on where exatly in the classloader hiearchy you class is actually located.
Multiple classloaders in general are a necessity, because it is sometimes needed to have different versions of the same class, p.ex. in different applications running on the same JVM.

Use of Thread's ContextClassLoader [duplicate]

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

The Java ClassLoader Security Model

I'm trying to understand the security model used when the JVM is asked to load classes.
From the JVM specification on Sandboxing, I'm given to believe that a standard JVM implementation should maintain at least one other ClassLoader, independent of the primordial ClassLoader. This is used to load the application class files (from a provided classpath for example).
If the class is requested from the ClassLoader that is not in it's namespace, java/lang/String for example, then it forwards the request to the primordial ClassLoader, which attempts to load the class from the Java API, if its not there then it throws a NoClassDefFoundError.
Am I right in thinking that the primordial ClassLoader only loads classes from the Java API namespace, and all other classes are loaded via a separate ClassLoader implementation?
And that this makes the loading of classes more secure because it means that a malicious class cannot masquerade as a member of the Java API (lets say java/lang/Virus) because this is a protected namespace, and cannot be used in the current ClassLoader?
But is there anything to prevent the Classes of the Java API being replaced by malicious classes, or would that be detected during class verification?
For historical reasons the names used for class loaders are a little peculiar. The boot class loader loads the systems classes. The system class loader, by default, loads classes from the class path not the system classes. The system classes are in jre/lib (mostly in rt.jar), endorsed directories and anywhere added through -Xbootclasspath.
On the Sun/Oracle JRE, rt.jar contains classes with packages starting with java., javax., sun., com.sun., org.omg, org.w3c and org.xml.
Untrusted code (including configuration) should not be able to add to the system classes. Some packages name prefixed may be restricted through a security property. The java. prefix is specially protected against for non-technical reasons.
Generally a class loader will delegate to its parent before defining a new class, preventing any classes from an ancestor loader from being replaced. Java EE recommends (even though Java SE bans) having some class loaders prefer their own classes, typically to use a more up to date API or a different implementation. This allows shadowing of classes, but only as seen through that loader (and its children). All other classes continue to link to the original.

Java is there a way to load a class that has been already loaded by the System ClassLoader by a different one?

(Terrible Title, I know)
The best way to explain this, is that I need to load some classes that will be loaded at Runtime from a URLClassLoader, by these classes have references to instances of classes that are already loaded by the System ClassLoader and they can't be reloaded because of some other issues.
Also, I am willing to change around my code so I can load classes from a jar in the class path with the System ClassLoader, but I haven't been able to do that.
No. Every classloader has the bootstrap classloader as an ancestor, and trying to load a class that is already defined in a classloader will just result in use of the ancestor's version. This is intentional to prevent java.lang.Object and other intrinsics from being redefined.
From the javadoc for ClassLoader:
The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.
You may be able to define a custom classloader that exposes defineClass without it being called by findClass and avoid the delegation that happens in findClass, but I would not rely on defineClass(className, bytes) working as intended on all JVMs when parent.findClass(className) exists.
Yes, you can define another classloader and load the class.
As per spec
"At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface."
Yes. But you need to be slightly careful because the default parent class loader is the system class loader, not the boot class loader. I suggest using java.net.URLClassLoader.newInstance(myURLs, null). If you want to be flash, get the parent class loader from the system class loader, and that will include extension classes.
(Note, terminology is a bit twisted because it dates from before Java2 when classpath included what is now bootclasspath (a pain for installers). So the system classes are not loaded by the system class loader.)

Unloading classes in java?

I have a custom class loader so that a desktop application can dynamically start loading classes from an AppServer I need to talk to. We did this since the amount of jars that are required to do this are ridiculous (if we wanted to ship them). We also have version problems if we don't load the classes dynamically at run time from the AppServer library.
Now, I just hit a problem where I need to talk to two different AppServers and found that depending on whose classes I load first I might break badly... Is there any way to force the unloading of the class without actually killing the JVM?
Hope this makes sense
The only way that a Class can be unloaded is if the Classloader used is garbage collected. This means, references to every single class and to the classloader itself need to go the way of the dodo.
One possible solution to your problem is to have a Classloader for every jar file, and a Classloader for each of the AppServers that delegates the actual loading of classes to specific Jar classloaders. That way, you can point to different versions of the jar file for every App server.
This is not trivial, though. The OSGi platform strives to do just this, as each bundle has a different classloader and dependencies are resolved by the platform. Maybe a good solution would be to take a look at it.
If you don't want to use OSGI, one possible implementation could be to use one instance of JarClassloader class for every JAR file.
And create a new, MultiClassloader class that extends Classloader. This class internally would have an array (or List) of JarClassloaders, and in the defineClass() method would iterate through all the internal classloaders until a definition can be found, or a NoClassDefFoundException is thrown. A couple of accessor methods can be provided to add new JarClassloaders to the class. There is several possible implementations on the net for a MultiClassLoader, so you might not even need to write your own.
If you instanciate a MultiClassloader for every connection to the server, in principle it is possible that every server uses a different version of the same class.
I've used the MultiClassloader idea in a project, where classes that contained user-defined scripts had to be loaded and unloaded from memory and it worked quite well.
Yes there are ways to load classes and to "unload" them later on. The trick is to implement your own classloader which resides between high level class loader (the System class loader) and the class loaders of the app server(s), and to hope that the app server's class loaders do delegate the classloading to the upper loaders.
A class is defined by its package, its name, and the class loader it originally loaded. Program a "proxy" classloader which is the first that is loaded when starting the JVM. Workflow:
The program starts and the real "main"-class is loaded by this proxy classloader.
Every class that then is normally loaded (i.e. not through another classloader implementation which could break the hierarchy) will be delegated to this class loader.
The proxy classloader delegates java.x and sun.x to the system classloader (these must not be loaded through any other classloader than the system classloader).
For every class that is replaceable, instantiate a classloader (which really loads the class and does not delegate it to the parent classloader) and load it through this.
Store the package/name of the classes as keys and the classloader as values in a data structure (i.e. Hashmap).
Every time the proxy classloader gets a request for a class that was loaded before, it returns the class from the class loader stored before.
It should be enough to locate the byte array of a class by your class loader (or to "delete" the key/value pair from your data structure) and reload the class in case you want to change it.
Done right there should not come a ClassCastException or LinkageError etc.
For more informations about class loader hierarchies (yes, that's exactly what you are implementing here ;- ) look at "Server-Based Java Programming" by Ted Neward - that book helped me implementing something very similar to what you want.
I wrote a custom classloader, from which it is possible to unload individual classes without GCing the classloader. Jar Class Loader
Classloaders can be a tricky problem. You can especially run into problems if you're using multiple classloaders and don't have their interactions clearly and rigorously defined. I think in order to actually be able to unload a class youlre going go have to remove all references to any classes(and their instances) you're trying to unload.
Most people needing to do this type of thing end up using OSGi. OSGi is really powerful and surprisingly lightweight and easy to use,
You can unload a ClassLoader but you cannot unload specific classes. More specifically you cannot unload classes created in a ClassLoader that's not under your control.
If possible, I suggest using your own ClassLoader so you can unload.
Classes have an implicit strong reference to their ClassLoader instance, and vice versa. They are garbage collected as with Java objects. Without hitting the tools interface or similar, you can't remove individual classes.
As ever you can get memory leaks. Any strong reference to one of your classes or class loader will leak the whole thing. This occurs with the Sun implementations of ThreadLocal, java.sql.DriverManager and java.beans, for instance.
If you're live watching if unloading class worked in JConsole or something, try also adding java.lang.System.gc() at the end of your class unloading logic. It explicitly triggers Garbage Collector.

Categories

Resources