I made a simple library for measuring the size of a given object. The library is
accessed through JNI from a Java class. It's specifically designed for Hotspot, thus it uses the JVMTI and it calls GetObjectSize.
My question is, what's the better solution?
To load the library using System.load("library") or
to set the library as an agent and explicitly load it by issuing the java command with the agent option.
All similar examples I've seen so far employ the agent function:
Determine Java class size from JNI jclass
How to calbulate the size of an object
In what way is that more efficient than just loading the library?
Thanks!
The advantage of command-line injection, is that the agent is loaded together with the Virtual Machine. You can inject the agent into every Java program without modifying the program. With System.load that this done at the point of invocation. You can react to a bigger set of callbacks, for instance there is a VM Initialization Event. If you use System.load that event is bygone.
As a result, I do not believe that using command-line injection is so much more efficient in a cetain way, but rather more effective for some use cases.
Related
We know that the JVM calls on the underlying system to allocate memory and CPU time, access files, and many more. How does it work internally to achieve its activities?
Does the JVM use system calls?
Does the JVM use system calls?
Yes.
How does it work internally to achieve its activities?
The typical pattern is that some of the methods in a Java class are labelled as native. When the JVM encounters a call to a native method it makes a call into C or C++ code that is part of the JVM executable. The native method implementation typically does the following:
Check arguments from Java, and translates them into a C / C++ compatible form. For example, String arguments need to be converted to zero-terminated form.
Call the standard C / C++ library function with the arguments it needs.
The library function makes the syscall.
The OS does its stuff and the syscall returns.
The standard C / C++ library function returns.
The native method implementation checks the 'errno'. If there was an error, it creates a Java exception object and throws it.
Otherwise, the native method implementation converts results, etc into Java objects and returns them to the caller of the Java method.
The details vary, depending on what the native method does.
If you want to get a deeper understanding, I recommend that you checkout a copy of the OpenJDK source tree and start trawling. (You need to do the hard yards yourself ....)
Indeed, JVM needs to leverage system calls which is an operating system way to allow processes to interact with underlying system resources.
You can run strace java -version to see a bunch of system calls (mmap, mprotect, openat, etc.) executed even during this very limited java/jvm run.
Another good way to find out more is to dig trough JVM sources for native methods.
One example could be an implementation of FileChannel#force method
which internally calls fsync system call (for example): https://github.com/AdoptOpenJDK/openjdk-jdk11u/blob/5f01925b80ed851b133ee26fbcb07026ac04149e/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c#L172
Yes, system calls are the only way that an OS allows access to any program.
In the case of Java, this is why some OS-specific “features” show through, so spoiling the ideal of write-once-run-anywhere. For example, I’ve had a program that I developed on a Windows box fail when run on a Linux box.
The problem turned out to be that in the resources directory, the filename was all-lower case, but my program had the file name inMixed case. The program worked on windows since filenames on windows are case-insensitive, but in Linux they are case-sensitive.
Is there a way to programmatically get the current jvm stats such as classes loaded or current heap size from C++? I know there are many tools to do so but I would like to integrate this with another application that would read these statistics from time to time.
You can have a look at JVMTI and JNI.
JVMTI allows you to attach a native agent to a Java application, with loads of low-level functionalities like heap traversals, etc. It also contains "Garbage Collection Start" & "Garbage Collection Finish" events, which could be used as starting points.
JNI allows you to call Java functions from native code (and vic-versa). I could imagine that you could use this technique to obtain information from ManagementFactory or some similar Java class that provides the needed information. This post contains a complete example on how to call static Java methods via JNI, which should be a good starting point.
I have a cross-platform Java application that relies on some native (C++) libraries for calling functions that perform complex scientific calculations. The native libraries are accessed using JNI (with SWIG-generated glue code). The libraries access several environment variables for configuration and location of various data tables, etc.
I would like my Java application to be able to set these environment variables, at least in the context of the JNI libraries. This would be easy if Java provided a way to set environtment variables in it's own shell/context, but it doesn't.
I've seen answers to similar questions that require changing variables for Java itself or for child processes. This question is different because it relates specifically to JNI-called code. My guess is that the situation is identical because the JNI code presumably runs in the same environment as the Java application itself.
However, I thought I'd ask just in case there is some JNI setting or method that could do this.
Your guess is correct. Environment variables are tied to the process. No difference between JNI and not-JNI.
You should be able to use another JNI library to set the environment for the other library running in the same process to pick up.
I have dll created in vb.net.
How can i use its functions in JAVA.
I found something JNI while searching on google , but not getting it.
Is there any simple documentation with example.
I would recommend Java Native Access (JNA) as its easier than using JNI. Lets say you have a DLL with some functions,
Create an java interface which has the same method signatures as the functions in DLL.
For example
public interface NativeExample{
public int method1(String param1);
public boolean mehthod2();
}
Now following is the way you load the DLL (assuming its name is NativeLib.dll)
NativeExample nativeExample= (NativeExample) Native.loadLibrary("NativeLib",
NativeExample.class);
Once you have this, you can call the method from the DLL via java methods.
`nativeExample.method("test");`
`nativeExample.method2();`
For mappings of the datatypes between Java and Native, please refer the the link above.
Here is one more example.
Exactly JNI will not give you direct access to .NET unless you work a lot on this. You can build own wrappers and use C/C++ as middle-ware but for small projects it will never pay off. Remember that calling method is one thing but passing arguments in proper types, retrieving results, subscribing events etc..etc.. is a lot more.
Therefore I would also propose to check for third-party tools which are well prepared for these kind of scenarios.
First check at least these two:
Javonet
JNBridge
Javonet I would recommend for all small and quick projects as this is light solution which provide very high performance due to in process communication and does all background work for you. All you need is call "AddReference(your.dll)" and next invoke any method using reflection-style API. You can invoke any methods, set/get fields and properties, get results, subscribe events or handle exceptions.
Very similar way works JNBridge which has a lit bit more additional staff/extensions for popular enterprise scenarios like cloud integration or websphere but this one I would recommend for bigger projects were you expect to bridge java and .net on separate machines it's more powerful but more complicated and heavy as well.
Both are free to try and Javonet is free for non-commercial and academic usage, so try, test and choose what best suits your requirements.
Well, there are third party tools / libraries that will help you connect Java to .NET. If you want to do it yourself -- meaning implement the JNI wrappers yourself -- you actually need to implement 2 sets of wrappers.
JNI will get you to C/C++, which is not allowed to directly access .NET objects. At that point, you can implement another wrapper, a .NET object with only static methods, that your C/C++ wrapper can call. Since unmanaged C/C++ code can't own .NET objects, it can only call static methods of .NET classes.
I'd like to know if it is possible to get the VM arguments using JNI?
Using the Invocation API allows you to specify the VM arguments if you are creating your own JVM.
What I'd like to be able to do is query these arguments in JNI from an already running JVM that has been lauched using the normal Java launcher. I believe that it must be possible because JMX is able to do so.
I've searched quite extensivley for this and as yet have not found a solution.
Thanks in advance
CND
PS. I know it is possible to query these using RuntimeMXBean.getInputArguments() but I need to do this natively in JNI.
RuntimeMXBean.getInputArguments() calls through to VMMangementImpl.getVmArguments which returns an immutable collections, making it difficult to tamper with.
http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/management/sun/management/VMManagementImpl.java.htm
It in turn calls a native method getVmArguments0() and the source for this method is available in the OpenJDK. You might be able to call whatever this method calls.