What is shared in a JVM - java

What do two different Java programs, running in one same Java Virtual Machine, share together?
Something comes to my mind, regarding singleton classes: They can only be instantiated once per JVM. This means that if two different Java programs use one same class, they are both accessing the same instance of that Singleton class?
What other things are shared?

If you run the java command multiple times, you get multiple instances of the JVM. In theory these are entirely separate with nothing shared, but some implementations of the JVM (now or in the past) might attempt to share some portions of the data.
I haven't looked at it recently, but about 10 years back there was a version of the Sun JVM that would attempt to "share" .class file images between JVM instances. (This was supposedly useful on servers where there might be dozens of JVMs running at once and they might come and go fairly rapidly.)
I'm not recalling any other data shared, but there may have been more, or other data may have been added since. (Though there really isn't much else that can be shared between JVMs.)
But again, in theory this should all be "transparent" and not affect the operation of an individual JVM instance.
There was also a provision for "warm started" JVMs that were partially loaded prior to the final command. This did require some configuration on the part of the system admin, but was otherwise transparent.

Two or more programs running in the same JVM shares everything. Regarding singleton, when written properly there will be one single instance of the class, which can be accessed by all the other objects.

Related

Two object instances of the same class running in separate JVM process

I have a simple Java SE application. It creates two instances of the same class, but each one must run in a separate JVM process. How can achieve that?
I have a simple Java SE application, it creates two instances of the same class, but each one must run in separate JVM processes, how can achieve that?
TL;DR:
You cannot achieve this, and you should not be wanting this, as it has no sense at all.
Fetus can not be living in two different mothers' wombs. It has to belong to either.
Little bit more:
When your run a Java program, for each and single Java application (e.g. either just manually packaged .class files, a .jar file, J2EE Container, or any other Java application), a discrete instance of JVM spins up on top of your OS kernel.
That JVM instance loads the corresponding bytecode, initializes Class Loader, allocates a memory and CPU time, and finally that's what you see as a running Java application.
If you, however, are talking about the Inter Process Communication and confused this with what you ask in your question, then I have to tell you that IPC is an ability when two (or more) JVM instances communicate between each other, and not to share on Java main class among several JVMs.
As JLS §5.2 says:
The Java Virtual Machine starts up by creating an initial class, which is specified
in an implementation-dependent manner, using the bootstrap class loader (§5.3.1).
The Java Virtual Machine then links the initial class, initializes it, and invokes
the public class method void main(String[]).
Hence, after bootstraping JVM, the main method is invoked after everything is linked and initialized. You can not even theoretically share this among two ore more JVM instances. Think about Class Loader, Garbage Collection, Linking Phase.. which should do what? which should bootstrap the main? which should maintain Class type instances for object instantiation?
Also, each JVM instance provides single kernel-level Input and Output stream to communicate with OS.
You can, somehow, achieve the vice-versa by running more than one Java applications in one JVM, but that has a lot of implications and problems, and is very much discouraged to do.
Last but not the least: Your System.in and System.out kernel-level I/O channels are the only instances from one JVM to the one OS Kernel. Bear this in mind as well, as in case of multiple JVMs running single Java application, this is a complete mess and confusion.

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.

Load existing class objects in JVM from another JVM

How to load existing class objects in JVM from another JVM?
I am analyzing a rare scenario in my server. I do not have proper logs in my sever to help me solve the situation and I believe that it can be a problem with a particular class object (user defined).
Say for example below is the class:
public class MyRequest
{
public byte[] getData()
{
return somdata;
}
}
Currently in my server's JVM, 100's of the above class object is in my JVM's memory. I want to know if there is a possibility to load all the 100 objects and access their data/method (getData()).
I do not want to create an new instance of the MyRequest class (that I know is pretty easy). I want to load the existing objects from my JVM through another Java process.
P.S : I can not kill my server for any reason.
P.S : And I can not install any tools like visualvm etc and more over tools tell us the objects type,memory but not the exact data.
Basically, it won't work.
If you can't attach a debugger, you can't do anything.
If you could attach a debugger, you should be able find and look at those instances, but you won't be able to get them to do something they weren't designed to do. In particular, if they are not designed to be serializable, you won't be able to serialize them.
I think your best bet is to change your server code to improve the logging, and then restart it with a debugger agent ... and wait for the problem to recur.
And of course, if you have a debugger attached, you don't need to move objects to another JVM. You can just look at their state directly.
However, there's a catch. Many "amazingly rare" scenarios are actually related to threading, thread-safety and timing problems. And many things you can do to observe the effects of a such a bug are liable to alter the program's behaviour.
FOLLOWUP
So if we know the starting address of the Virtual memory for that JVM...can we not know the data? assuming all objects are within the JVM memory space.
It is not as simple as that:
Locations of objects on the Java heap are not predictable.
Locations of thread stacks are not predictable.
and so on.
It may be theoretically possible to dump the memory of any process, and reconstruct the execution state of the JVM, and "read" the state of the objects. But you'd need specialized tools and/or a great deal of knowledge of JVM internals to do this. I'm not even sure if the tools exist ...
In short, it is not practical, AFAIK.
Objects and their references (aliases) are bound to the current running JVM. There is no possibility to share them between several JVMs.
If you want to "share" data between two JVMs, you must serialize this data, which means sending them from on JVM to the other. This also requires the classes, whose instances shall be serialized, to implement the interface Serializable. Note, that arrays automatically implement Serializable.
You can either stream those serializable objects yourself using sockets, output and input streams (which is much effort) or you can use RMI for calling remote methods and just stream your data. In either case, all objects are copied and built up again in the other JVM. There is no chance to have them shared.
In case of application servers, RMI calls are typically invoked by just using EJBs. But you need an application server; just using a web server is not enough.
Load existing class objects in JVM from another JVM
Its not possible
Note that you can tell the JVM to dump its state - with a kill signal or similar - to disk so you can use post-Mortem tools to analyze the state of your program.
Keywords are "core" and "hprof" and I have not done this myself yet.

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

Possible Memory leak in Number of Loaded classes in Java Application

I recently began profiling an osgi java application that I am writing using VisualVM. One thing I have noticed is that when the application starts sending data to a client (over JMS), the number of loaded classes starts increasing at a steady rate. The Heap size and the PermGen size remains constant, however. The number of classes never falls, even after it stops sending data. Is this a memory leak? I think it is, because the loaded classes have to be stored somewhere, however the heap and permgen never increase even after I run the application for several hours.
For the screenshot of my profiling application go here
Are you dynamically creating new classes on the fly somehow?
Thanks for your help. I figured out what the problem is. In one of my classes, I was using Jaxb to create an XML string. In doing this, JAXB ueses reflection to create a new class.
JAXBContext context = JAXBContext.newInstance(this.getClass());
So although the JAXBContext wasn't saying around in the heap, the classes had been loaded.
I have run my program again, and I see a normal plateau as I would expect.
I'm willing to bet that your problem is related to bytecode generation.
Many libraries use CGLib, BCEL, Javasist or Janino to generate bytecode for new classes at runtime and then load them from controlled classloader. The only way to release these classes is to release all references to the classloader.
Since the classloader is held by each class, this also means that you should not release the references to all classes as well [1]. You can catch these with a decent profiler (I use Yourkit - search for multiple classloader instances with the same retained size)
One catch is that the JVM does not unload classes by default (the reason is backwards compatibility - that people assume (wrongly) that static initializers would be executed only once. The truth is that they get executed every time a class is loaded.) To enable unloading, you should pass some use the following options:
-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
(tested with JDK 1.5)
Even then, excessive bytecode generation is not a good idea, so I suggest you look in your code to find the culprit and cache the generated classes. Frequent offenders are scripting languages, dynamic proxies (including the ones generated by application servers) or huge Hibernate model (in this case you can just increase your permgen).
See also:
http://blogs.oracle.com/watt/resource/jvm-options-list.html
http://blogs.oracle.com/jonthecollector/entry/presenting_the_permanent_generation
http://forums.sun.com/thread.jspa?messageID=2833028
You might find some hotspot flags to be of use in understanding this behavior like:
-XX:+TraceClassLoading
-XX:+TraceClassUnloading
This is a good reference:
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
Unless I misunderstand, we're looking here at loaded classes, not instances.
When your code first references a class, the JVM has the ClassLoader go out and fetch the information about the class from a .class file or the like.
I'm not sure under what conditions it would unload a class. Certainly it should never unload any class with static information.
So I would expect a pattern roughly like yours, where as your application runs it goes into areas and references new classes, so the number of loaded classes would go up and up.
However, two things seems strange to me:
Why is it so linear?
Why doesn't it plateau?
I would expect it to trend upwards, but in a wobbly line, and then taper off on the increase as the JVM has already loaded most of the classes your program references. I mean, there are a finite number of classes referenced in most applications.
Are you dynamically creating new classes on the fly somehow?
I would suggest running a simpler test app through the same debugger to get a baseline case. Then you could consider implementing your own ClassLoader that spits out some debug information, or maybe there is a tool to make it report.
You need to figure out what these classes being loaded are.
Yes, it's usually a memory leak (since we don't really deal with memory directly, it's more of a class instance leak). I've gone through this process before and usually it's some listener added to an old toolkit that didn't remove it self.
In older code, A listener relationship causes the "listener" object to remain around. I'd look at older toolkits or ones that haven't been through many revs. Any long-existing library running on a later JDK would know about reference objects which removes the requirement for "Remove Listener".
Also, call dispose on your windows if you recreate them each time. I don't think they ever go away if you don't (Actually there is also a dispose on close setting).
Don't worry about Swing or JDK listeners, they should all use references so you should be okay.
Use the Eclipse Memory Analyzer to check for duplicated classes and memory leaks. It might happen that the same class gets loaded more than once.
Regards,
Markus

Categories

Resources