How jvm distributes between tomcat and deployed Java applications - java

We have Tomcat deployed with two Java based web applications. How can I tune the performance of one of the applications without affecting the other one if they are running in the same JVM?

Your tomcat run in a JVM with both your applications. All 3 run in the same JVM. So if you tune the JVM (like max memory usage), everything will be affected by it. As far as I know there is no ways to indicate that you want more resources allocated to 1 of your applications.

The two web applications are deployed within the same JVM (including tomcat). So there is just one JVM that tomcat and the two web applications reside in. This is your current scenario.
On the other hand if you would like to tune the web applications separately - say in terms of performance etc. then the easiest thing would be to deploy them on two different hosts / machines. This way the two web applications would be running in their own JVM and would be completely isolated from each other and can be tuned independently. Note: you would need to think this through in terms of requirements of another host and yet another for a reverse proxy. See EJP's comment below.
If that is not possible then you could have two different JVMs brought up each with a tomcat and one of the web applications. This way you could tune the two JVMs separately: you could tune the tomcat servers running separately within the two different JVMs, you could attempt to run them with different allocations of OS resources etc. But that is an involved topic for another discussion. How would you achieve two different JVMs running a tomcat and one of the web application each? To achieve that you utilize the CATALINA_BASE approach wherein the two web applications are deployed to two differently located "webapps" folders. I will not go into details on this but leave you with a link. Note: you might need a reverse proxy as well in this case.
With the two different JVM approach (two different java processes), the respective JVMs can be tuned separately. I prefer this approach as this way it is easier to have separate things like log configurations, restart one without affecting the other and so on.
Since you are talking about performance, let me also mention in passing that whatever approach you might take, keep in mind that that in certain Operating Systems especially linux, you could restrict or allocate resource such as cpu, memory etc. to a particular process (JVM in your case). You could also utilize containers such as Docker to do the same. Maybe you are already aware of this, but I mention for completeness.
you can refer to: tomcat - CATALINA_BASE and CATALINA_HOME variables

Related

Confused about Java Memory [duplicate]

Is the same JVM used by all Java applications running or, does 'one JVM per Java application' apply? (say the applications are IntelliJ IDEA, a server and NetBeans for example)
Further, is there any connection between JVMs assigned and processes used by each Java application?
Generally speaking, each application will get its own JVM instance and its own OS-level process and each JVM instance is independent of each other.
There are some implementation details such as Class Data Sharing, where multiple JVM instances might share some data/memory but those have no user-visible effect to the applications (except for improved startup time, hopefully).
A common scenario however is a single application server (or "web server") such as Glassfish or Tomcat running multiple web applications. In this case, multiple web applications can share a JVM.
There's one JVM per Java application. There shouldn't be any connection between them unless you establish one, e.g. with networking. If you're working inside of an IDE, the code you write generally runs in a separate JVM. The IDE will typically connect the separate JVM for debugging. If you're dealing with multiple web applications they could share the same JVM if they're deployed to the same web container.
In theory you can run multiple applications in a JVM. In practice, they can interfere with each other in various ways. For example:
The JVM has one set of System.in/out/err, one default encoding, one default locale, one set of system properties, and so on.
If one application changes these, it affects all applications.
Any application that calls System.exit() kills all applications.
If one application thread goes wild, and consumes too much CPU or memory it will affect the other applications too.
Short answer: often, yes, you'll get one application per JVM.
Long answer: the JVM can be used that way, and that may be the best option, but it doesn't have to be.
It all depends on what you consider to be an 'application'. An IDE is a good example of an application which is presented to its end users (i.e. us) as a single entity but which is actually comprised of multiple underlying applications (compilers, test runners, static analysis tools, packagers, package managers, project / dependency management tools, etc). In that case there are a variety of tricks which the IDE uses to ensure that the user experiences an integrated experience while also being shielded (to some extent) from the individual vagaries of the underlying tools. One such trick is to do some things in a separate JVM, communicating either via text files or via the application-level debugging facilities.
Application servers (Wildfly, Glassfish, Websphere, Weblogic, etc) are applications whose raison d'etre is to act as containers for other applications to run in. In that case, from one perspective, there's a single JVM per application (i.e. one JVM is used to run the entire application server) but there are actually multiple applications contained within that JVM in their own right, each logically separated from each other in their own classloader (reducing the possibility of accidental in-process crosstalk).
So, it all really depends on what you consider an application to be. If you're purely talking about "the thing which runs when 'main()' is called", then you're looking at one application per JVM - when the OS starts the JVM, the JVM runs a single class's public static void main() method.
But once your applications start getting more complicated your boundaries become more blurred. An IDE such as Intellij or Eclipse will reuse much of the same stuff as 'javac', either in the same JVM or a different one, as well as doing different work (such as repainting the screen). And users of a web application on a (shared JVM) application server may actually be using much the same 'core' application as could be used locally via the command line.
Number of JVMs running is the number of executables invoked.
Each such application invokes its own java executable (java.exe/ javaw.exe etx for windows) which means each is running in a separate JVM.
Any application which has shared libraries will share the same copy of those libraries. Java has a fair amount of shared libraries. However, you won't notice the difference except for some memory saved.
Little late here however this info may be useful for somebody. In a Linux system, if you want to know how many JVMs are running you can try this command
$ ps -ef | grep "[j]ava" | wc -l
ps to list process, grep to search process containing "java" and wc to count lines returned
Actually this is one question that can have very confusing answers. To keep it real short:
Yes per java process, per JVM.
Runtime and ProcessBuilder follow this rule.
Loading jars using reflection and then executing the main won't spawn new JVM.

Is it bad to have two webapps on a machine each on different servlet container than both on same?

I need to run two webapps on a ubuntu VPS but one(my own webapp) prefers to run in Tomcat & other(Solr webservice) is preferable in Jetty. But I think running a separate server for each webapp would be consuming more resources (like memory consumption would be higher) than both the webapps running on same server, isn't it ?
What may be the other bad if I run both Tomcat & Jetty on a single machine for production use?
A couple of things I can think of, some of which you've mentioned:
more resources are consumed (memory usage of two containers running
is generally going to be more than one container running). Also, there could be implications for things like database connections and caching if you have two containers instead of one.
containers have to run on different ports (but there are ways to make it appear to the site visitor that they're on the same port)
don't forget that containers generally listen on more than one port, so you'll have to make sure you avoid conflicts (think of tomcat shutdown port, etc).
Having said that, I run tomcat and jetty side by side all the time on my dev machine and things work just fine. But development, not performance, is my major goal when running on my dev machine.
Running Tomcat and Jetty in the same machine is something that "performance wise" is not so "heavy", I have both running (almost) all the time in my dev machine... in production I am using only Tomcat (running multiple web services in the same container - mainly my web services + Solr) and I do not experience major differences on performance in both scenarios. So I would say that it depends on your needs... personally I tend to prefer to simplify my production setup and avoid having multiple containers in multiple ports on my servers. Furthermore, Tomcat does seem to be more popular solution for java container (http://zeroturnaround.com/rebellabs/the-great-java-application-server-debate-with-tomcat-jboss-glassfish-jetty-and-liberty-profile/), this does not however mean it is the best one for all scenarios. I personally tend to stick with one Tomcat in production...
Yes, it does consume more resources to run two instead of one, but for development purposes it shouldn't be a problem as long as your personal computer isn't terribly under powered. Other than that, you will have to resolve any port conflicts that come up when you start the second process. The error messages should tell you what port is conflicted and all port numbers are configurable.

Setting the multiple JREs in the same application

I have implemented one application using JDK 1.6 64-bit, JSF, Tomcat server 64-bit etc at user system.I am integrating some devices(i.e. finereader, scanner, etc) into this application. Some of devices libraries are supported only on JRE 32-bit Only.
So, device integrated screens to be run on JRE 32-bit and non device screens should be run on a JRE 64-bit. Can I configure multiple JRE's in the same application? If possible, how?
A Java application runs in a JVM. The JVM is part of one single JRE. You could split your application into two parts, which each run in their own JVM. These applications then would have to communicate with each other to coordinate the user experience. This does not look like a good solution to me.
It all depends on how you define "application."
First, in regard to your question, each JVM instance runs a single kind of Java--32 or 64 bit--Java version and such.
Sometimes, an application consists of a single JVM running a single java executable, usually a jar and some stuff on the classpath with a single 'main'
Sometimes, an application consists of multiple JVMs running on one or more boxes. In this case, each JVM is running a single java executable. But there has to be some sort of communication between these executable parts to make it function as an application.
Alternatively, the same executable might run on multiple JVMs and we still call it one application. In this case, there would be some sort of outside stuff that decides how to allocate the work of the application amoung the multiple JVMs. For example, you could run 18 instances of Tomcat on 9 boxes with a hardware load balancer dividing up the network requests and assigning each one to one of the Tomcat instances. In this case, though, part of the application is probably running on 1000's of user's computers inside a browser.
Sometimes, we say multiple applications are running under another application. In this case, we might call the master application a container. One example is Tomcat. In this case, Tomcat manages the load of requests for each of the separate applications because the HTTP requests come in off the network with information in the header indicating which one handles that request.
You already say that you have some code running under Tomcat. Tomcat is a single executable (It runs in one JVM and has one variety of Java) and it manages running your one Java executable supplied as a .war file, usually. There could be other Java applications running in other JVMs that communicate through that Tomcat and with your executable. Or there might not be other JVMs that your executable communicates with running somewhere else.
So, you can see, the real answer is "it depends." If you have multiple JVM communicating in some way, you could have different Java varieties. If it's all running under a single Tomcat instance, then you have a single variety of Java.

Why have one JVM per application?

I read that each application runs in its own JVM. Why is it so ? Why don't they make one JVM run 2 or more apps ?
I read a SO post, but could not get the answers there.
Is there one JVM per Java application?
I am talking about applications launched via a public static void main(String[]) method ...)
(I assume you are talking about applications launched via a public static void main(String[]) method ...)
In theory you can run multiple applications in a JVM. In practice, they can interfere with each other in various ways. For example:
The JVM has one set of System.in/out/err, one default encoding, one default locale, one set of system properties, and so on. If one application changes these, it affects all applications.
Any application that calls System.exit() will effectively kill all applications.
If one application goes wild, and consumes too much CPU or memory it will affect the other applications too.
In short, there are lots of problems. People have tried hard to make this work, but they have never really succeeded. One example is the Echidna library, though that project has been quiet for ~10 years. JNode is another example, though they (actually we) "cheated" by hacking core Java classes (like java.lang.System) so that each application got what appeared to be independent versions of System.in/out/err, the System properties and so on1.
1 - This ("proclets") was supposed to be an interim hack, pending a proper solution using true "isolates". But isolates support stalled, primarily because the JNode architecture used a single address space with no obvious way to separate "system" and "user" stuff. So while we could create APIs that matched the isolate APIs, key isolate functionality (like cleanly killing an isolate) was virtually impossible to implement. Or at least, that was/is my view.
Reason to have one JVM pre application, basically same having OS process per application.
Here are few reasons why to have a process per application.
Application bug will not bring down / corrupt data in other applications sharing same process.
System resources are accounted per process hence per application.
Terminating process will automatically release all associated resources (application may not clean up for itself, so sharing processes may produce resource leaks).
Well some applications such a Chrome go even further creating multiple processes to isolate different tabs and plugins.
Speaking of Java there are few more reasons not to share JVM.
Heap space maintenance penalty is higher with large heap size. Multiple smaller independent heaps easier to manage.
It is fairly hard to unload "application" in JVM (there to many subtle reasons for it to stay in memory even if it is not running).
JVM have a lot of tuning option which you may want to tailor for an application.
Though there are several cases there JVM is actually shared between application:
Application servers and servlet containers (e.g. Tomcat). Server side Java specs are designed with shared server JVM and dynamic loading/unloading applications in mind.
There few attempts to create shared JVM utility for CLI applications (e.g. nailgun)
But in practice, even in server side java, it usually better to use JVM (or several) per applications, for reasons mentioned above.
For isolating execution contexts.
If one of the processes hangs, or fails, or it's security is compromised, the others don't get affected.
I think having separate runtimes also helps GC, because it has less references to handle than if it was altogether.
Besides, why would you run them all in one JVM?
Java Application Servers, like JBoss, are design to run many applications in one JVM

Resource management in tomcat

We have several Java web-applications that need to be deployed on the same machine, over tomcat. The web-applications are not related to each other. Some of them do intensive I/O and CPU operations and consume much memory.
Under the above conditions, which approach is recommended - having a single tomcat with multiple webapps, or multiple tomcats each running a single webapp ?
If all webapps are deployed on the same tomcat, is there a way to guarantee minimum resources per webapp ? I.e. minimum amount of memory, number of threads, etc.
Thanks,
Arnon.
What we did at our company is we run 1 application per instance of Tomcat. We originally started with multiple instances and it occurred occasionally that one application would affect the other, especially if you had to restart the Tomcat instance.
One thing that might be worth evaluating is Spring's TC Server.
http://www.springsource.com/developer/tcserver
Similar to #tjg184 's experience. I would recommend running a tomcat per application instance. If you have a decent config and process management system, the incremental cost is not all that high and it gives you the best isolation possible without separate vm's for each tomcat instance. You could start with a single tomcat and some solid monitoring and then see if you need to move to one tomcat per app.

Categories

Resources