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.
Related
I apologize in advance if the answer to this question is a simple one. It seems I don't have enough knowledge about classloading in Java.
Say I have a file called "properties" in my application. My application uses an external JAR and inside that JAR, there's also a file called "properties".
Question:
If the external JAR file attempts to open that file with getClass().getClassLoader().getResourceAsStream("properties"), why doesn't it load the one from my application. Not that I want it to, but wouldn't the ClassLoader in this case be the one that loaded my application? I thought that method would use the absolute path for finding the resource. Do classes in external JARs get loaded with a different classloader?
The class loading mechanism is the same for classes and resources (but the bytes found are treated differently).
See http://docs.oracle.com/javase/tutorial/ext/basics/load.html for the official explanation.
It is the first class loader actually asked which has the resource that wins. If the class loader does not have its resource, try again with the parent.
(Note that for web applications - WAR files - this is deliberately slightly different about which one is asked first).
ThClassLoader#getResourceAsStream(String) calls getResource(String) and this as getResource() on the parent. If this does not find anything, then it will ask the classloaders findResource(String).
It depends on this implementation what it does return, in case of the URLClassLoader this will be URLClassPath.findResource() which steps through all loaders (one loader for each search path entry) and returns the first find.
In a normal application your JARs as well as all libraries are loaded by the same (Application) class loader. In case of the Sun launcher this is sun.misc.Launcher$AppClassLoader which extends URLClassLoader. It puts all JAR and classes from the classpath in the search list.
It is a good idea to make resources either unique (putting them in your packages) or retrieve all resources and pick the right one (or all). The later is for example used by the ServiceLoader when it finds all implementations for a given service.
No, it loads the first found in that class' classloader. If you want to open a file using an absolute path, you open an InputStream pointing at the file.
Classes in external JAR might be loaded using different classloaders (e.g. in a Java EE container) but then classloaders need to be chained in order for you to see them.
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.
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.
A problem: My application uses two libraries which use incompatible versions of a third library. Does someone know any method for classes isolation?
I have heard about class loaders, but I do not understand, how they could help - if we will load one version of class, we cannot load another - class is already loaded?
I also thinking about Spring, but do not know if it provides such isolation.
ClassLoaders are basically the elements that gives meaning to classes in the JVM. They form a hierarchy for wich the root lies in the JVM and loads java classes. The ApplicationClassLoader is the first ClassLoader you have to consider, as it loads all the classes of your application.
When a class is loaded, all its references to other classes are resolved and theses classes are loaded. The JVM by default provides a system where classloaders ask their parent first to see if they have already loaded a class. If not, they search in their classpath
Two classes can be isolated if they live in 2 different classloader, and not in the app classloader. It's not difficult to do. You only have to create a classloader (like URLClassLoader) while specifying its parent and its classpath(the place where the bytecode is)
then, you tell him to load a class. It will ask its parent, and if the class is not loaded yet, it will search its classpath and load it. If you create another classloader attached to the same parent, the classes loaded by the first will never be seen by the seconds as they are siblings. And the second can loads a class with the same name without any problem
That's quite a good isolation
App Servers use another form of delegation to have a frank isolation between applications. they redefine a classloader extending, for example, URLClassLoader and reverse the delegation process by starting to search for classes in their classpath first, then ask to the parent
if we will load one version of class, we cannot load another - class
is already loaded?
Not true. The class loader is considered part of the class's identity. If it's loaded by a different classloader, it's considered a different class.
If at least one of the libraries is open source, and the library they depend on is open source, no need for messing about with classloaders. Just bulk rename all the packages in one of the versions of the library being depended on, making sure to also change all code which refers to those packages. Hey presto - no name clashes. This is what Sun actually did for the JDK, when they included Xerces and Xalan behind the scenes.
I have two jar files from a client, one of which is used for a testing and another for final versions. Currently I put them in different folders and modify the library path when deploying our code, but it would be nice to be able to load both jar files and switch between them dynamically at runtime.
Is this possible?
You can always write your own ClassLoader and chain it with the standard ClassLoader.
http://download.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html
I used this method 10 years ago to load classes that were recieved via sockets and specified in an XML file (via sockets as well). My java program didn't know that the classes even existed before it got the XML file and the classes.
Using OSGi bundles you can do that. Take a look at http://blog.springsource.com/2008/02/18/creating-osgi-bundles/. Search for "multiple versions".
justinjh,
chrisparker2000's suggestion looks to be the most feasible - You have to write a custom classloader, the only change that I can think of is something along the following lines:
1. For the client deliverable jars - say client.dev.jar and client.prod.jar, rename to a different extension and place these in the classpath. Rename to a different extension to prevent the container from loading the contents of the jar.
Using the custom classloader, load the contents on demand, based on the solution offered by chrisparker2000, by placing a small facade on top of the client classes, say ClientClassFactory which based on the environment(dev/prod/anything else) would use the custom classloader to load from either client.dev.otherext or client.prod.otherext .
If you use a build-tool like maven, you can define different jar files (dependencies) for different scopes (test vs production).
You may also use maven profiles to define different set of jar files/versions.