Skip to content

Debugging UnsatisfiedLinkError and StackOverflowError on Linux

Gertjan Al edited this page Dec 8, 2016 · 2 revisions

Given:

static {
    // Register all formats and codecs
    avformat.av_register_all();
}
// ffmpeg code usage

Might cause a StackOverflow or UnsatisfiedLinkError

Caused by: java.lang.StackOverflowError
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at org.bytedeco.javacpp.Loader.loadLibrary(Loader.java:637)
at org.bytedeco.javacpp.Loader.load(Loader.java:492)
at org.bytedeco.javacpp.Loader.load(Loader.java:409)
at org.bytedeco.javacpp.avcodec.<clinit>(avcodec.java:13)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.bytedeco.javacpp.Loader.load(Loader.java:464)
at org.bytedeco.javacpp.Loader.load(Loader.java:409)
at org.bytedeco.javacpp.avformat.<clinit>(avformat.java:14)

java.lang.StackOverflowError

Check if the Error is still thrown when using java -jar {file} -Xss512k to increase the stack size.

java.lang.UnsatisfiedLinkError

First, enable debugging, for example by adding slf4j / log4j dependency and configuring debug level:

Loading class org.bytedeco.javacpp.avutil
Loading class org.bytedeco.javacpp.avutil
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libavutil.so.55
Loading /tmp/javacpp28873975186486211/libavutil.so.55
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniavutil.so
Loading /tmp/javacpp28873975186486211/libjniavutil.so
Loading class org.bytedeco.javacpp.swresample
Loading class org.bytedeco.javacpp.avutil
Loading class org.bytedeco.javacpp.swresample
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libswresample.so.2
Loading /tmp/javacpp28873975186486211/libswresample.so.2
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniswresample.so
Loading /tmp/javacpp28873975186486211/libjniswresample.so
Loading class org.bytedeco.javacpp.avcodec
Loading class org.bytedeco.javacpp.avutil
Loading class org.bytedeco.javacpp.swresample
Loading class org.bytedeco.javacpp.avcodec
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57
Loading /tmp/javacpp28873975186486211/libavcodec.so.57
Extracting jar:file:/opt/myapplication/lib/ffmpeg-3.1.2-1.2-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniavcodec.so
Loading /tmp/javacpp28873975186486211/libjniavcodec.so
(exception occurs here)

In case of a failing load of .so file, you can use ldd -v libjniavcodec.so and objdump -p libjniavcodec.so to investigate the dependencies of the lib.

Example output:

$ ldd -v libjniavcodec.so
	linux-vdso.so.1 =>  (0x00007fff90bfe000)
	libavcodec.so.57 => /tmp/javacpp90472456501071/./libavcodec.so.57 (0x00007fc31350e000)
	libswresample.so.2 => /tmp/javacpp90472456501071/./libswresample.so.2 (0x00007fc3132f2000)
	libavutil.so.55 => /tmp/javacpp90472456501071/./libavutil.so.55 (0x00007fc31307b000)
	libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc312d52000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc312a4b000)
	libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc312835000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc312470000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc312251000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc31204d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fc315475000)

Also see: http://www.oracle.com/technetwork/java/javase/crashes-137240.html#gbyzz

4.1.3 Crash due to Stack Overflow

A stack overflow in Java language code will normally result in the offending thread throwing java.lang.StackOverflowError. On the other hand, C and C++ write past the end of the stack and provoke a stack overflow. This is a fatal error which causes the process to terminate.

In the HotSpot implementation, Java methods share stack frames with C/C++ native code, namely user native code and the virtual machine itself. Java methods generate code that checks that stack space is available a fixed distance towards the end of the stack so that the native code can be called without exceeding the stack space. This distance towards the end of the stack is called “Shadow Pages.” The size of the shadow pages is between 3 and 20 pages, depending on the platform. This distance is tunable, so that applications with native code needing more than the default distance can increase the shadow page size. The option to increase shadow pages is -XX:StackShadowPages= n, where n is greater than the default stack shadow pages for the platform.