I'd like to be able to read data from a separate JVM (essentially "peek" into it) at will so I can read specific class instance values and/or invoke methods. I've looked into using both agents and the attach API but each of them seems to only be designed for runtime instrumentation and not being able to grab the actual instance itself.
An instance of an object only exists in one JVM if you use managed memory.
If you use a data structure which uses shared memory, you can do this e.g. Chronicle Map This makes memory accessible to multiple JVMs, but only by using off heap, shared memory.
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.
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.
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 have a use case where I have to run a java application multiple times.
Performance bottleneck for the application is it's initialization time.
At initialization, application loads 10 million records from disk into memory data structure
and then application does around 100 million lookups in the in-memory data structure.
What I want to do is to avoid loading the records from disk again and again.
And my application to use shared memory for the data structure lookup.
I don't want to use remote method calls/web service call since that would be too costly
for the lookup part.
Also, I don't have the option to use threads.
I would build the data structure in memory mapped files. These can be shared between processes and runs of the same process. Using them is not trivial however as you have to determine how you will structure the data at the byte level. i.e. you can't use Java objects. (On the plus stide this means almost no GC overhead)
Ideally you should make this application into a server and the command you run should get required data via request-response mechanism.
Another option can be to create a snapshot of the required data which can be very quickly loaded everytime you run the program.
Though I've never used it but looks like Class Data Sharing might help you.