I am confused at a point while running my application. My application consists of EJB and servlets. i need to know, whether the class loader for these application types is same or different. I am using weblogic as application container.
Please help me.
There is one class in my application which is singleton and class loader dependent.And the problem is that the instance of my class changes when class loader changes, and i need to use the same instance of the class through out the life time.
Yes there is a system classloader that all of the webapp classloaders will delegate to.
To get your class into that classloader, you need to make sure it is in the relevant classpath. For instance with Tomcat, you would put the JAR file into $CATALINA_HOME/lib (... if I'm remembering that correctly).
That having been said, I'm not convinced that sharing application singletons between multiple webapps is good design.
You'll find that each application is typically loaded into it's own instance of a class loader. The class loader is going to be a class provided by the web container, but there will be one instance of it for each application running. This allows applications to be isolated from each other, and many instances to be loaded, regardless of whether they are using static/class variables, or singletons etc.
WebLogic uses layered class loader. How is your application packaged? Is it EAR or WAR + JAR's?
This link will be helpful.
Related
Java has 3 class loaders:
BootStrap,
Extension and
System
and they have one role; loading classes from different packages.
But why does Java have 3 different class loaders instead of just one, since one class loader can load all the necessary classes?
The reason for having the three basic class loaders (Bootstrap, extension, system) is mostly security.
Prior to version 1.2 of the JVM, there was just one default class loader, which is what is currently called the "Bootstrap" class loader.
The way classes are loaded by class loaders is that each class loader first calls its parent, and if that parent doesn't find the requested class, the current one is looking for it itself.
A key concept is the fact that the JVM will not grant package access (the access that methods and fields have if you didn't specifically mention private, public or protected) unless the class that asks for this access comes from the same class loader that loaded the class it wishes to access.
So, suppose a user calls his class java.lang.MyClass. Theoretically, it could get package access to all the fields and methods in the java.lang package and change the way they work. The language itself doesn't prevent this. But the JVM will block this, because all the real java.lang classes were loaded by bootstrap class loader. Not the same loader = no access.
There are other security features built into the class loaders that make it hard to do certain types of hacking.
So why three class loaders? Because they represent three levels of trust. The classes that are most trusted are the core API classes. Next are installed extensions, and then classes that appear in the classpath, which means they are local to your machine.
For a more extended explanation, refer to Bill Venners's "Inside the Java Virtual Machine".
The main usage of class loaders is in application servers.
You want to be able to start Tomcat (for example). This already needs at least one classloader to run tomcat itself.
Then you want to be able to deploy an application into Tomcat. So Tomcat itself needs to load an analyze the classes of the application, which didn't even exist when Tomcat was started.
Then you want to be able todeploy another application in Tomcat. Maybe this second application uses a library that the first one also uses, but in a different version. So you want each app to have its own isolated class loader, otherwise the classes of app 2 might interfere badly with the classes from app 1.
Then you want to be able to undeploy one of the webapps. So its class loader must be destroyed and garbage-collected, to avoid a huge memory leak.
There are of course many other usages, but that's the one that is the most commonly used (in my experience).
Multiple class loaders are present to load multiple applications
simultaneously(One to load Server & Other to deploy in the server).
Each loader has a hierarchy to load only certain
classes to ensure security among them.
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.
As per my understanding there will be one jvm instance and one class loader hierarchy per war file. Right? Two questions:-
Question1:- if i package my servlet class and business class(packaed in jar file) in war file.So war file here contains jar file and servlet class. If i try access static global variable declared in servlet in business class, i can do it Correct? because here will be only one jvm instances and class loader hierarchy
Question2:-In same scenario as above if i package my servlet class and business class in two different war files both packaged under same ear file then If i try access static global variable declared in servlet in business class, i can not do it .Is it Correct? because here will be two jvm instances and class loader hierarchy per war file
Of course the entire application server runs in a single JVM (at least that's true of all application servers I know of). There is no need to launch a separate JVM to give each web application a dedicated class loader that sees different (versions of) classes.
So war file here contains jar file and servlet class. If i try access static global variable declared in servlet in business class, i can do it Correct?
You probably can, but you should not, as it violates the layering of your application if the business layer relies on the presence of a particular class from the presentation layer.
if i package my servlet class and business class in two different war files both packaged under same ear file then If i try access static global variable declared in servlet in business class, i can not do it .Is it Correct?
Again, this is bad design. Moreover (as far as I know) the specification does not mandate a particular behaviour that is adhered to by all application servers, so this is likely to depend on your choice of application server and its configuration.
There is no reason for a web container to start a new JVM instance for each web application (either deployed using a war file or by simple copying of what would be inside the war into the './webapps/' directory in e.g. Apache Tomcat). Different web apps are usually started using different class loaders to securely separate them from each other. This is no standard, just the way things are usually done by web containers.
There are no 'global static' variables in Java (not by this name), what you mean are 'public static' class fields/variables. These are only accessible by classes loaded by the same classloader (that are contained in the same web app). (Also presuming they have access to the containing class as a class may have default access which disallows some classes, even loaded by the same classloader, from accessing its members).
The way you try to access stuff from different wars is bad design as explained in meriton's answer.
1) Use ServletContex for sharing data within same web app as described in gertas' answer.
2) If you really need to, you may share data between different web apps using JNDI.
3) Also consider if what you really need is not sharing data, but messaging or full fledged persistence mechanism.
You are right, one class loader per WAR, separate static variable scopes between WARs, but not exactly two JVM instances. Usually servlet container runs under one JVM.
But using static variables to exchange data (constants are ok) is bad design I would suggest using ServletContext. See also Servlet context scope vs global variable .
Question1:
As we know, when a classloader is about to load a class, it delegates the request to its parent classloader. However in Tomcat, it doesn’t: you could load your class to overwrite the same name class which is put in common lib directory. This means Tomcat WebappClassloader doesn’t follow delegating policy. Is it violation of convention?
Question2:
I wrote a class and put it in common lib directory, obviously the class is shared among web apps. For instance, every web app can read/write the static field of the class. Further, classes in JDK are loaded by Bootstrap classloader, then their static fields are shared by any web apps, is it dangerous?
This behavior is intentional and it allows you to override libraries provided in the Tomcat itself independently in every WAR. For instance you can override Log4J with different version per each application deployed to the container without introducing any issues or breaking other applications. From Tomcat documentation:
Like many server applications, Tomcat installs a variety of class loaders [...] to allow different portions of the container, and the web applications running on the container, to have access to different repositories of available classes and resources. This mechanism is used to provide the functionality defined in the Servlet Specification, version 2.4 — in particular, Sections 9.4 and 9.6.
It does violate the normal delegation algorithm, but this is how other application server work as well (JBoss for instance).
Ad. question 2: Yes, it is dangerous, you have to remember about synchronization and have no control over who modifies this variable. I would avoid static fields altogether.
For instance EhCache allows you to share CacheManager. This is implemented via net.sf.ehcache.CacheManager#singleton static volatile field. Now you get all sort of problems: if you put ehcache.jar in Tomcat's /lib, it will work as expected. However if each web application has its own copy of the JAR file, sharing will not work because each web app has its own copy of CacheManager class. It gets even worse when only one application has its own ehcache.jar - all applications will share the same instance of CachedManager except the one having ehcache.jar packaged together. Such error are very hard to track down...
Why is the setContextClassLoader() method placed on Thread?
What different thread have different classloaders?
The question is what if I extended a ClassLoader, loaded there some new classes. to the my custom classloader.
Now , I want it to be the context classloader , so I call the method Thread.currentThread().setContextClassLoader(loader).
Are these new classes awailable only in the context of the current thread ? Or how does it work?
Thanks
The Context class loader is the class loader that the thread will use to find classes. You primarily care about this when you are writing an application server or something similar. The idea is that you can start a thread from a class loaded in the application server's class loader, and yet pass it a child class loader that handles loading the classes of the deployed application.
The thread context class loader is a little bit of a hack.
When you load a class with reflection, you use either an explicit class loader or the one of the immediate calling class. When you link to a class using normal Java code, then class requesting the linking is used as the source for the loader.
Thread.setContextClassLoader is used to set the class loader for Thread.getContextClassLoader. This is used by random APIs (notably through ServiceLoader) to pick up classes through reflection so that you can change implementation. Having implementations change out from under your code depending upon which thread it is running on at a crucial moment is a bad idea.
Thread.setContextClassLoaderis used to set contextClassLoader, if not set manually, it will set to systemClassLoader which is Launcher.AppClassLoader ,this can be proved by checking the source code of Launcher.
Then what is the use of contextClassLoader?
contextClassLoader provides a back door around the classloading delegation scheme.
Then this question becomes why do we need this back door?
From the JavaWorld article Find a way out of the ClassLoader maze
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.
Java class loaders can be classified into below categories
1) Bootstrap Class Loader
Load classes from JAVA_HOME/jre/lib/rt.jar
2) Extensions Class Loader<
Load classes from JAVA_HOME/jre/lib/ext
3) System Class Loader
Classpath of the application
We can create own class loader and specify own location from which classes can be loaded , that is refer to ContextClassLoader
Hope that gives idea upon why we need to use setContextClassLoader()