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.
Related
I have a C shared library that is used from a Java application via JNI. I need to store some expensive-to-calculate data which will be valid for the lifespan of a JavaVM. I would like to store this in a static variable in C, so that it gets calculated exactly once.
Of course, this will fail if it is possible for my library to be used from multiple JavaVMs in the same process. My static values would only be valid in the first JavaVM. If my library is being loaded from Java via System.loadLibrary in a static block on a class, is it ever possible for said library to be used across multiple JavaVMs without having to completely unload my C shared library?
Yes. Most popular JVM implementations, in particular, HotSpot JVM and its derivatives, allow only one Java Virtual Machine per process.
In fact, an implementation allowing multiple VMs in one process, will not be compliant with the JNI specification, as the documentation to JNI_CreateJavaVM and JNI_GetCreatedJavaVMs explicitly says that
Creation of multiple VMs in a single process is not supported.
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.
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.
I'm trying to figure out how the JVM works with regard to spawning multiple threads. I think my mental model may be a little off, but right now I am stuck on grokking this idea: since there is only one copy of the JVM running at any time, wouldn't each thread require its own copy of the JVM? I realize that the multiple threads of a java application are mapped to native os threads, but I don't get how the threads that are not running the JVM are crunching bytecode; is it that all threads somehow have access to the JVM? thanks, any help appreciated.
but I don't get how the threads that are not running the JVM are crunching bytecode; is it that all threads somehow have access to the JVM?
http://www.artima.com/insidejvm/ed2/jvmP.html explains this well. Here is what it says:
"Each thread of a running Java application is a distinct instance of the virtual machine's execution engine. From the beginning of its lifetime to the end, a thread is either executing bytecodes or native methods. A thread may execute bytecodes directly, by interpreting or executing natively in silicon, or indirectly, by just- in-time compiling and executing the resulting native code. A Java virtual machine implementation may use other threads invisible to the running application, such as a thread that performs garbage collection. Such threads need not be "instances" of the implementation's execution engine. All threads that belong to the running application, however, are execution engines in action."
Summarizing my understanding of this:
For every thread (execpt GC thread and ilk), corresponding ExecutionEngine instance (in the same JVM) converts bytecodes to machine instructions and native OS thread executes those machine instructions. Of course, I am not talking about green thread here.
This is a bit oversimplified and some of what I wrote isn't strictly correct, but the essence is this:
since there is only one copy of the JVM running at any time, wouldn't each thread require its own copy of the JVM?
Not really. You could permit multiple threads to read from one piece of memory (as in same address in memory) and thus have only one JVM. However, you need to be careful so that threads don't create a mess when they access such shared resources (JVM) concurrently, as it is the case in the real world (imagine two people trying to type two different documents at the same time with one PC).
One strategy of having multiple threads working okay together with some shared resource (such as JVM (stack, heap, byte code compiler), console, printer etc.) is indeed having copies for each threads (one PC for each person). For example, each threads has its own stack.
This is however not the only way. For example, immutable resources (like class byte codes in memory) can be shared among multiple threads without problem through shared memory. If a piece of memo doesn't change, two people can both safely look at that memo at the same time. Similarly, because class byte code doesn't change, multiple threads can read them at the same time from one copy.
Another way is to use a lock to sort things out between the threads (whoever is touching the mouse get's to use the PC). For example, you could imagine a JVM in which there is only one byte code interpreter which is shared among all threads and is protected by one global lock (which would be very inefficient in practice, but you get the idea).
There are also some other advanced mechanism to let multiple threads work with shared resources. People who developed the JVM used these techniques and that's why you don't need a copy of JVM per thread.
By definitions threads in a Java application share the same memory space, therefore are executing within the same JVM. This way you can easily share objects across multiple threads, perform synchronization and such, all that is happening within the JVM.
One way to see it is that processes have their own memory space, while threads within an application share the same memory space.
Does invoking java via two different command line involves two different JVMs or two separate instances of same JVM.
JVM is Java Virtual Machine, a memory space where classes (code) are loaded and objects (data) are shared. JVM is equivalent to an Operating System process.
When you type java... in you command line you are executing an independent process that loads Java classes in memory, the base classes from Java and yours (from the .class files or .jar you indicate).
Another java... command will load a different process with its own memory and will load classes by itself.
Instance word confusion: when you say 'two instances of the same JVM'. It's usual to say instance of a JVM to a separate process, it is, to a loaded independent JVM. If you are saying: two process are running JVM 1.5, OK, it's the same JVM in the sense it's the same version but they are different processes, different 'instances', independent in all sense.
Webapp confusion: A webapp (by example) is simply a bunch of classes and objects instantiated, attending some URL in a web server. You can start Tomcat with 10 different apps -it is, 10 different bunches of classes and objects each of them attending different request, but in fact they share the same memory space (OS process). A webapp cannot touch other webapp's objects because nobody gives it a reference to the other objects (and classes are in some way hidden but that's another story called: class-loading).
What is the difference in your question? I would say: two different JVM instances. :)
Each run of the the java command does invoke a new JVM instance. The running java application could run new Java Threads (like a Tomcat does with web applications).
Two separate JVMs. You can run lots of stuff inside the same JVM (say 10 webapps served up by the same Tomcat instance), but there is only 1 java command to start tomcat.
If you started Sun's java.exe from their JDK/JRE version 1.6 from the same source path twice, you would get two separate and distinct JVM instances. There would be no sharing between them unless you configured it via your applications. If you wanted two different JVM's running you would have to start a java.exe of one type (say 1.5) from one location and a java.exe (version 1.6) from another.
If you are using one JDK version to run your project for both instances, invoking java via two different command lines will involve two different instances of the same JVM
If you are using a different JDK version for each app, this will involve two different JVMs.