I am having difficulty in understanding the significance of classLoader in ResourceBundle.getBundle(bundleName, locale, classLoader) API .
What could be the practical scenario where someone would want to provide custom loader for this API?
A Java application might have multiple class loaders. For example, a J2EE application running on Tomcat or Glassfish has multiple tiers of classloaders - some belonging to the J2EE server itself, some being specifically made for your webapp (otherwise your webapp would be able to access classes belonging to other webapps) and even custom classloaders that you might have instantiated yourself.
Standalone Java apps might also have multiple classloaders. For example, if your application supports plugins and each of these plugins is contained in its own JAR file (local or remote) then in order to load the plugin's classes at runtime you would have to create your own classloaders to do so.
Therefore, when you load a ResourceBundle you have to select the appropriate classloader to ensure that the resource is loaded from the correct source. Here's a simple example... imagine that your application contains a /version.properties file and your JVM also has a similar, yet different, /version.properties (e.g. IBM's Java has this properties file). Trying to load this resource file using the system's default classloader returns the version.properties that is included in the JVM and in order to load your own version of this file, you must use a custom classloader or one whose context is specific to your app.
There is an old but still very interesting explanation of how class loaders work and how hierarchies and loading contexts are useful in practice. For more info, check Internals of Java Class Loading.
Related
Java ClassLoader delegation model means:
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.
I have seen the question.Generally we should use it. But I want to know more. Is there any good reasons that we should not use it?
The answer of the linked question and the Tomcat classloader documentation that is quoted there seems to provide a good use case: web containers like Tomcat, that run isolated web applications.
You "generally" want to the use delegation model to avoid different parts of your application to load classes with different class loaders, because otherwise classes would be loaded multiple times but would not be compatible with each other. This is useful for single applications - but web containers and applications servers can run multiple applications where you actually want applications to be able to load their own versions of some classes.
For example, with Tomcat each of the running web applications might use a different set of libraries or different versions of the same library. There are a few shared repositories for libraries that should be available for all web application and also an application-specific repository for each web application.
Each repository has its own class loader. Here is Tomcat's class loader tree, with parent class loaders at the top:
Bootstrap
|
System
|
Common
/ \
Webapp1 Webapp2 ...
The application specific repositories should have priority, because they may contain other library versions than the shared repositories.
I found the following loaders structure for OSGi in internet.
bootstrap classloader (Java standard libraries from jre/lib/rt.jar
etc) ^ extension classloader ^ system
classloader (ie stuff on $CLASSPATH, OSGi core code) ^ (**
limited access to types from parent classloader common OSGi
classloader:
--|-- OSGi classloader for bundle1 -> (map of imported-package->classloader)
--|-- OSGi classloader for bundle2 -> (map of imported-package->classloader)
--|-- OSGi classloader for bundle3 -> (map of imported-package->classloader)
Here it says that
A context classloader set on the executing thread. By default it is
always set to System classloader or from the thread from where the new
thread instance was created.
From structure above we see system loader(=context loader) has higher position and as I know parent classloader never asks its children.
So my question please explain how current thread works with classes that are in current bundle?
In OSGi the Thread Context ClassLoader (TCCL) is simply undefined. You cannot expect or assert that it will be anything in particular. In fact, a lot of the time it will be null.
TCCL is a hack that was added in Java 1.2 to support J2EE. Specifically it was needed to support things like Entity Beans; in a modern world it's used to support technologies like JPA, JAXB, Hibernate and so on.
The issue with parent delegation is that, while the application classes at the bottom have visibility of all classes in the parent classloaders, unfortunately the classes loaded by the parent classloaders do not have visibility of the application classes. In practical terms, this means that your application code can load (say) the classes that make up Hibernate, but Hibernate would not be able to load your domain classes because they are below it in the hierarchy.
So, TCCL was invented. In a J2EE application server, the TCCL is created as a thread-local variable, and it has visibility of all your application classes. Hibernate/JPA/JAXB etc can consult the TCCL in order to find the application classes. This was easy enough to do in J2EE because the app server controls all of the entry points: it controls the web server, it controls the RMI endpoints, and as an application developer you are not permitted to create your own threads.
However the programming environment for OSGi is far less constrained. Any bundle is permitted to create its own network endpoints, spin up its own threads, or pretty much do anything. Therefore, OSGi has no opportunity to intervene and impose a TCCL that has visibility of the application classes. Furthermore, the very concept of an "application" is fuzzy because we have this neat thing called modularity. An application consists of multiple bundles... but how to define which bundles may provide classes to the TCCL?
So OSGi basically punts on this issue. The TCCL is undefined so you should never rely on it. Fortunately most libraries that try to use only do so as one of a series of places they try to load classes from.
Web applications for Tomcat are wrapped into a .war file and thrown into Tomcat. The application can use classes inside the war file and contained jar files. This separates the runtime-classes of Tomcat from the application classes.
When using storm (see storm-project.net), there is no similar segregation. Rather the recommended way requires to create a "fat jar", denoting a jar containing all the necessary class files after unwrapping them from their own individual jars. For simple situations this works, but the resulting fat jar must have all the META-INF/* files from all merged jars correctly merged, which does not work semi-automatically.
I would not be shy to write my own class loader which simulates something like a war-file. Except I have no clue how to intercept the default class loader that loads all the classes I deploy.
My theory is that one of the classes of my applications is loaded first by the default class loader. Presumably in its static-section I would cast the magic class loader spell such that all dependent classes will then be loaded by my own class loader, which would now how to get the necessary classes from whatever I deem suitable.
Any hints towards the general problems described as well as the specific magic needed are appreciated.
Intercepting the classloader: The default classloader is the one which loaded the class that is currently executing. So if you use a separate classloader to bring in the WAR's entry point, every class reference from it or its (run-time/creation) descendents will default to going through that classloader. That classloader can then decide what it should refer back to a higher-level classloader and what it should reload using its own resolution rules -- the simple rule "only ask the parent for things I don't have available in this plug-in", also known as "parent last", is often sufficient.
What is need for an application or system to go for Custom class loader?
What are the limitations of the current set of classloaders that generally web application use ( Server + JVM )
Regards
Illustrate one of the usage of Custom class loader, I will take an example of my implementation,
Couple of months ago I have built a custom class loader to load a class created at run time from xml data source. The requirement was to create a java source files from a XML files, compile, jar it.
In order to load/execute these classes which resides in a DB I had to write custom class loader (extending URLClassLoader) since all the operation happening at run time, default/system classloader is not aware of the new classes(jar) , or not in the claspath.
We have used custom classloaders in our application to build a plugin framework. This classloader allowed us to embed jar files inside the plugin file (Which is also a jar file).
You can create your own ClassLoader to
1. Create new classes (for example, when custom proxying needed)
2. Redefine existing classes, when on some reason java.lang.instrumentation (javaagent) is not available.
The difference that I read on the Internet between Java EE and Java SE classloading is that
In Java SE, a classloader delegates the classloading to its parent
classloader and then tries to load the class itself
However, In Java EE, a classloader first tries to load the class itself and then
delegate the classloading of that class to its parent classloader.
Kindly validate my understanding.
Also, why is it designed like that in Java EE (Any advantages of keeping it like this.)
This is the link where I heard this [http://www.youtube.com/watch?v=t8sQw3pGJzM]
Alright then,
A common application has 3 standard classloaders:
Bootstrap Classloader
Extensions Classloader
System-Classpath Classloader
So far, so good. Now, this works for a single application running alone and free.
But what happens when you say J2EE? You have multiple applications running on the same place, so you have to figure out a way to prevent them from stumbling on each other. That's where these extra classloaders come into play.
Think about a server instance. There's a JBoss with two deployed EARs. What would happen if there were to be conflicting classes between applications? They're ok on their own particular context but as a whole they're inconsistent.
These extra classloaders are introduced in an application-wise way to ensure the isolation between them. Classloaders below System-Classpath Classloader recognize a class only if it is specified in the manifest file for one of its childs.
In J2SE, the three basic classloaders work in a parent-child relationship based on three principles:
Delegation: If a class is not loaded (cache), the request is delegated to its parent. This goes on until the top of the hierarchy (Bootstrap classloader) who loads basic J2SE related classes (i.e. Integer, ArrayList, amongst others). This is what you reference in your question: A classloader delegates the loading until the top of the hierarchy, then each classloader tries to load the class if its parent couldn't find it, until someone loads it. Otherwise: ClassNotFound.
Visibility: Classes loaded by a parent classloader are visible to its children, not the other way around.
Uniqueness: If a parent classloader loads a class, a children will never reload it.
In Java SE, a classloader delegates the classloading to its parent classloader and then tries to load the class itself.
True, due to the principles explained above.
There's no determined classloader structure in J2EE (a vendor has "poetic license" to implement it), but they kind of follow a hierarchy. In this case, the System-classpath classloader loads the main application: The server. The server libraries (its classes, more specifically) are available, then, to every application due to the visibility principle.
Down there, the applications have particular classloader structures, but as a whole they are different children of the System-classpath classloader. Each application loads its related and particular classes (both application and libraries).
The loading here is not propagated to the parents outside the application context. Why? because if the System-classpath classloader were to load the applications as usual, the class of every application would be visible to others due to the visibility principle, completely breaking the isolation between themselves. So:
However, In Java EE, a classloader first tries to load the class itself and then delegate the classloading of that class to its parent classloader.
This is partly true, but I'd rather limit this affirmation to the context of an application and leave out the Java related classes, that are indeed loaded by the top level classloaders.
Long story short: It's not a straightforward process but I wouldn't go as far as to say J2EE handles the classloading the opposite way around of J2SE.
I think Java EE class loading standard will help you on your way. As far as I know there is no mandated way of classloading for standard Java. For WebApps (WARs) however, it is specified that the classloading is parent-last.