I had to link my java app to an external library using JNA.
I don't have its source and then I can't change it.
Sometimes happeneds that this external library crash the jvm of my app, I don't know what can be... Maybe an unmanaged exception of the external library, what I see is just a app crash when an external native method is called.
Is there any way to avoid the entire jvm crash and simply get an Exception by JNA?
To better detail the problem: this library is a smartcard driver. During some s.o. auto-update or after the s.o. standby process sometimes I got that crash. No logs or errors, just the end of the jvm process.
JNA provides a system property, jna.protected, which if set true will result in an exception rather than a crash. This is enabled by default on windows, but on other platforms you need to pre-link with libjsig.so, since JNA uses some of the same signals used by the JVM to catch memory faults.
From the JavaDoc:
It is not uncommon when defining a new library and writing tests to
encounter memory access errors which crash the VM. These are often
caused by improper mappings or invalid arguments passed to the native
library. To generate Java errors instead of crashing the VM, call
Native.setProtected(true). Not all platforms support this protection;
if not, the value of Native.isProtected() will remain false.
NOTE:
When protected mode is enabled, you should make use of the jsig
library, if available (see Signal Chaining) to avoid interfering with
the JVM's use of signals. In short, set the environment variable
LD_PRELOAD (or LD_PRELOAD_64) to the path to libjsig.so in your JRE
lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before
launching your Java application.
Even so, it's not recommended for production code, and certainly not recommended to attempt to continue execution after the fault occurs.
Related
I have an exe that is starting a JVM and loading java classes into memory. I was successfully able to dump these classes with a -javaagent from the running JVM by attaching it to the process and retransforming the classes. Now I am trying to modify the classes as they are loaded. My issue is that my java agent cannot handle premain as I cannot add command line options without modifying the loader executable, which is packed with Themida. By the time my java agent has been attached, the classes to be modified have already been loaded. I was thinking I could use the JVMTI class load hook to capture the class file and transfer it to a separate JVM and modify it with javassist or ASM then return it to to the original JVM via the JVMTI Agent. If I use JVMTI I'd need to load my agent with -agentlib, which brings me back to the problem of having to modify the executable. Can you think of any other ways I could preform this modification? Could I modify the JVM itself to load a java agent always on startup? Is there some other way to force the JVM to always load a java agent? To see if the software was calling any sort of exe in the JRE, I removed all of the exes from j64\bin. The program still loaded without error. When I removed java.dll, the program failed to load entirely, while the program still loads but throws an error when other dlls are removed. If I found which JRE dll was receiving the command line args from the loader, could I implement a dll proxy? Is java.dll the dll I'd want to proxy?
I can't really speak to the idea of proxying the jvm.dll. Sounds like very delicate and error-prone work. Don't know much about Themida either, but from some cursory browsing, you would be deliberately breaking Themida's security intent.
Without the ability to change JVM command line parameters, you don't really have a lot of options. (Rhetorical: What do you do if you need to change heap sizes etc. ?)
However, if you can append and additional execution after the JVM launches, you could use a JVM Attach execution to connect to the running JVM and and load your JVMTI agent via loadAgent. It's a real race-condition threat since your app could very well be under-way by the time you get your instrumentation installed, but as I said, your options are limited.
I would look into how you can use Themida to re-package the application and introduce a proper javaagent command line parameter. Plus, if you don't, you may find that Themida may detect your workarounds and disable them, or disable the JVM altogether.
I have a Java 1.6 application that accesses a third party native module, through a JNI class provided as the interface. Recently we noticed that a SEGFAULT is occurring in the native module, and is causing our application to crash. Is it possible to catch and handle this event, at least to log it properly before dieing?
I tried both Java techniques in the article from kjp's answer. Neither worked. Attempting to install a signal handler on 'SEGV' results in the exception
Signal already used by VM: SEGV
The shutdown handler I installed simply failed to fire, presumably because of what the IBM article states:
Shutdown hooks will not be run if
Runtime.halt() method is called to terminate the JVM. Runtime.halt() is provided to allow a quick shutdown of the JVM.
The -Xrs JVM option is specified.
The JVM exits abnormally, such as an exception condition or forced abort generated by the JVM software.
If all you want to do is log and notify you can write a script which runs your application. When the application dies, the script can detect whether the application terminated normally and from the hs_errXXXX file which has all the crash/SEGV information and mail it to someone (and restart the application if you want)
What you need to do is to run the faulty JNI code in another JVM and communicate with that JVM using RMI or JMS or Sockets. This way when the library dies, it won't bring down your main application and you can restart it.
Based on several weeks of research at the time, as well as conversations with JVM engineers at a conference this is not possible. The system will not let you install a SignalHandler on the SEGV signal.
I have a Java application on a USB stick along with the JRE (one for each Windows, Mac OSX and Linux) so that it can be run on any system even when Java is not installed. I have a thread running to detect if the USB stick is removed and if it is it exits the application.
I want to have it display a message before exiting (or tell them to re-insert the drive) but if I try to dispaly a JOptionPane I get the NoClassDefFoundError because the JRE has been removed along with the USB.
Is there a way to keep the needed classes in memory so that Java does not try to load them from the filesystem that is no longer present?
Thanks!
For most runtimes, any classes that are loaded will be in RAM, in the PermGen section of Java's memory.
To my mind what's likely happening is that displaying the error requires classes that haven't been loaded before - which are only available on the drive that's no longer there.
You might be able to work around this by triggering your error displaying logic when the program starts up, except have it in a mode where it's displayed invisibly. This should exercise the same code path such that all the required classes are loaded, and ensure that they're already known when you need to display your error. If this is too difficult, you could just manually call Class.forName("javax.swing.JOptionPane") instead (for each class required), though this is more brittle and likely to break if you change your rendering code without updating the hard-coded classes to load.
If this isn't the case (i.e. all the required classes have previously been loaded, and you still have the problem) then your runtime is obviously unloading classes. You'd have to look at its documentation to see what it's doing here, and how to stop it.
I have coded a Java application that through JNI calls a linear programming solver written in C++. After a number of successful calls I get an EXCEPTION_ACCESS_VIOLATION error and the application terminates.
How can I dismiss the error and keep the Java application operating?
First of all, if a dll crashes then the JVM will terminate.
This is one of the drawbacks of using JNI in the first place. So it is generally not as simple as swallowing some exception from the dll.
In your case the error hints towards unitialized memory. You should look towards out of bound indexing in your code.
You should post your code though in order to get more help
There is no way to keep JVM running if there is access violation happened in native code.
There are several things you can do.
Best - carefully debug your lib without JNI, with small standalone C++ client, and find the reason of this violation, and add excessive checks around that (incorrect pointer usage, incorrect memory cleanup etc)
Run your DLL in a separate JVM process, which is purely responsible for providing this solver functionality, communicate with second JVM using sockets, tcp-ip, soap, rest - whatever you prefer. Than, use some like Java Service Wrapper to run this second JVM and configure it in the way that it restarts the JVM if it crashed.
What is the best practice to solve a Java VM crash if the follow conditions are true:
No own or third party native code. 100% pure java
The same program run on many other system without any problems.
PS: With VM crash I means that the VM write a dump file like hs_err_pid1234.log and terminate.
Read the hs_err_pid1234.log file (or whatever the error log file name is). There are usually clues in there. The next step depends on what you discover in the log.
Yes, it could be a bug in the specific version of the JVM implementation you are using, but I have also seen problems caused by memory fragmentation in the operating system. Windows, for example, is prone to pin dlls at inappropriate locations, and fail to allocate a contiguous block of memory when the JVM asks for it as a result. Other out opf memory problems can also manifest themselves through crash dumps of this type.
Update or replace your JVM. If you currently have the newest version, then try an older one, or if you don't have the latest version, try updating to it. Maybe its a known issue in your particular version?
Assuming the JVM version across machines is the same:
Figure out what is different about the machine where the JVM is crashing. Same OS and OS version? We have problems with JVMs crashing on a particular version of Red Hat for example. And we have also found some older Red Hat versions unable to cope with extra memory properly, resulting in running out of swap space. (Our solution was to upgrade RedHat).
Also, is the program doing exactly the same thing across machines? Is it accessing a shared filesystem? Is the file system mounted similarly on your machines (SMB/NFS etc)? Something must be different.
The log file should give you some idea of where the crash occurred (malloc for example).
Take a look at the stacktraces in the dump file, as it should tell you what was going on when the crash occurred.
As well as digging into the hs_err dump file, I'd also submit it to Sun or whomever made your JVM (I believe there are instructions in how to do so at the top of the file?). It can't hurt.
32bit? 64bit? Amount of ram in client machine? processor? os? See if there is any connection between the systems. A connection may lead to a clue. If all else fails, consider using different major/minor versions of the JVM. Also, if the problem JUST started can you get to a time (via version control) where the program didn't crash? Look through the hs_err log, you may get an idea of what caused the crash. It could be a version of some other client library the JVM uses. Lastly, run the program in debug/profile and maybe you'll see some symptons before the crash (assuming you can duplicate it)