Am I guaranteed to have exactly one JavaVM per process using JNI? - java

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.

Related

In Java, can I decide where is my field stored: in register, cache or RAM?

I know that it is done automatically - the more frequently a piece of data is accessed, the closer to the processor it is stored. But can I somehow influence their placement with Java syntax? Volatile, the way I understand it, puts data in level 3 cache or RAM since it's visible to all the threads, is that right?
No, Java syntax does not allow direct access to the hardware. The Java language and virtual machine specification is the contract governing how Java code is interpreted - and it is explicitly written to target a Virtual Machine instead of an actual one.
From Section 1.2:
The Java Virtual Machine is the cornerstone of the Java platform. It
is the component of the technology responsible for its hardware- and
operating system-independence, the small size of its compiled code,
and its ability to protect users from malicious programs.
The Java Virtual Machine is an abstract computing machine. Like a real
computing machine, it has an instruction set and manipulates various
memory areas at run time. It is reasonably common to implement a
programming language using a virtual machine; the best-known virtual
machine may be the P-Code machine of UCSD Pascal.
There is no need for a Java VM to even have accessible registers or caches. From the point of view of the specs, a Turing Machine could very well implement a conformant Java VM.
Java works differently regarding optimisations to a large degree. You the the developer say what to do in your code. Then, at runtime, the just in time compiler looks at what is going on, and then (if necessary) translates "slow" java byte code into highly optimized machine code.
In other words: the JIT decides what code is worth optimizing. That might include optimized "data layouting".
But as said: you as a developer have "no say" in this.
You can't control this behavior.
If the CPU reads a field of an object the object is pulled into the L1d. This is independent of the field being volatile or not.
It doesn't matter if a field is accessed only once or many times; it will still end up in the L1d. Unless you have a non temporal load/store; but this behavior is not accessible from Java.
Volatile prevents reordering of instructions on both compiler and CPU/memory-sub-system level. In case of the X86, the volatile read you get for free (acquire semantics) due to the TSO memory model of X86. The volatile write is implemented by stopping the front-end from executing loads till the store buffer has been drained. This prevents the reordering of older stores with newer loads to a different address.
For more information see:
https://shipilev.net/blog/2014/on-the-fence-with-dependencies/

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.

Calling C++ library function using JNI and which process executes that C++ library

I am new to Java & JNI. This question maybe very newbe. I have C++ library and Java application which interns call the C++ function using JNI concepts.
As per my understanding, JVM loads the C++ dll/SO in JVM space before calling a native function call.
If my understanding on the JVM is correct on JNI. Can someone tell me which/who is going to execute the C++ library function which is loaded inside the JVM.
Let say for C++, there is standard dynamic linker-loader present to handling the dynamic execution part of the C++ and executes all the machine instructions.
In case of JVM loaded JNI Libs (in this case C++ libs), does JVM executes the those libs ? If so does it uses its memory to execute the native function?
Thanks in advance.
The Java language allows you to mark certain methods as native. The Java Native Interface allows you to link these Java methods to a function address in native code.
When you System.loadLibrary a library that contains native code, the JVM will do two things:
Look for specifically named functions such as Java_pkg_Cls_f_ILjava_lang_String_2 and link this to the function f in class pkg.Cls.
Call JNI_OnLoad, if it exists in the library. This can perform initialization and optionally link more native methods using registerNatives.
After this point, the native library indeed resides in the process' memory space like any other library (say, libcurl or libssl). When you actually call one of the native methods, the JVM will find the function address and use a native call instruction to jump into the function. The function will execute as part of the stack trace of that thread and will show up as such in both the JVM and native stack traces.
In more advanced cases, the library might spawn additional native threads. These work like regular threads in native code and are invisible to the JVM. If these threads need to talk to the JVM as well, the developer can attach them.

Get loaded classes within ANOTHER JVM

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.

Calling JNI_CreateJavaVM function twice

I'm using a library that calls the JNI_CreateJavaVM function inside the library code. However, I also need some JNI Wrappings and I need to call the same function JNI_CreateJavaVM to get the JNIEnv* to my application.
But the second call is failing.
is there any way to do this?
The library does not support getting or setting the JNIEnv* created inside the library.
You cannot create more than one JVM from the same process:
As of JDK/JRE 1.2 , creation of multiple VMs in a single process is not supported.
You may be able to attach your current thread to the existing JVM though using AttachCurrentThread function. See the docs for the Invocation API. The equivalent document in Java 15 simply states:
Creation of multiple VMs in a single process is not supported.
You will need a pointer to the JavaVM object. See if JNI_GetCreatedJavaVMs() can help you, I'm not sure if this is per-process (in which case it will only ever be a single element list) or per machine. In either case the JavaVM will have to be the one that the library is using or you probably will not be doing what you want. If you can access that then you should be able to make invocations on other objects in your Java application, but make sure that it is thread-safe.

Categories

Resources