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 .
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.
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.
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...
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.