bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.5k stars 1.58k forks source link

java.lang.NoClassDefFoundError running javacpp on Linux #832

Closed chammond75 closed 6 years ago

chammond75 commented 6 years ago

Sorry for the multiple posts but I'm really trying to get some help resolving this issue. I'm trying to use the FFmpegFrameGrabber class on an Alpine Linux system in order to do some frame grabs from videos (hls and mp4 format). I continue to run into the following error:

Error loading class org/bytedeco/javacpp/Loader. java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.javacpp.avcodec at java.lang.Class.forName0(Native Method) ~[?:1.8.0_131] at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_131] at org.bytedeco.javacpp.Loader.load(Loader.java:739) ~[javacpp-1.3.3.jar:1.3.3] at org.bytedeco.javacpp.Loader.load(Loader.java:684) ~[javacpp-1.3.3.jar:1.3.3] at org.bytedeco.javacpp.avformat$AVFormatContext.(avformat.java:2819) ~[ffmpeg-3.2.1-1.3.jar:1.3.3] at org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe(FFmpegFrameGrabber.java:509) ~[javacv-1.3.3.jar:1.3.3] at org.bytedeco.javacv.FFmpegFrameGrabber.start(FFmpegFrameGrabber.java:503) ~[javacv-1.3.3.jar:1.3.3]

Here's my linux version: Linux version 4.9.27-14.31.amzn1.x86_64 (mockbuild@gobi-build-60006) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) #1 SMP Wed May 10 01:58:40 UTC 2017 Here's my gradle dependencies: compile group: 'org.bytedeco', name: 'javacv-platform', version: '1.3.3' compile group: 'org.bytedeco.javacpp-presets', name: 'opencv-platform', version: '3.2.0-1.3' compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.2.0-1.3', classifier:'linux-x86_64' compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg-platform', version: '3.2.1-1.3' compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.2.1-1.3' compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.2.1-1.3', classifier:'linux-x86_64' This Linux box is running inside of a Docker image. I've tried building ffmpeg directly as part of the construction of the docker image (as seen here: https://hub.docker.com/r/opencoconut/ffmpeg/~/dockerfile/). That did not work. I tried opening up all the *linux-x86_64* jars and copying all the .so's to my /lib directory. That did not work. I'm a n00b at ffmpeg. I have my code working just fine on my Mac laptop that I use for development. I was hoping the linux box would similarly "just work". Please if anyone @saudet or anyone else has any clues I really need to get this figured out. Any additional info that I can provide please just let me know. Or any additional debug steps I can take just let me know. Thank you. EDIT: Here's my ffmepg setup on the box itself. I just realized that this may be old: fmpeg version 3.2.1 Copyright (c) 2000-2016 the FFmpeg developers built with gcc 6.3.0 (Alpine 6.3.0) configuration: --enable-version3 --enable-gpl --enable-nonfree --enable-small --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libvpx --enable-libtheora --enable-libvorbis --enable-libopus --enable-libass --enable-libwebp --enable-postproc --enable-avresample --enable-libfreetype --enable-openssl --disable-debug libavutil 55. 34.100 / 55. 34.100 libavcodec 57. 64.101 / 57. 64.101 libavformat 57. 56.100 / 57. 56.100 libavdevice 57. 1.100 / 57. 1.100 libavfilter 6. 65.100 / 6. 65.100 libavresample 3. 1. 0 / 3. 1. 0 libswscale 4. 2.100 / 4. 2.100 libswresample 2. 3.100 / 2. 3.100 libpostproc 54. 1.100 / 54. 1.100 EDIT 2: fwiw I updated ffmpeg on the box. Still no luck ffmpeg version 3.4 Copyright (c) 2000-2017 the FFmpeg developers built with gcc 6.3.0 (Alpine 6.3.0) configuration: --enable-version3 --enable-gpl --enable-nonfree --enable-small --enable-libmp3lame --enable-libx264 --enable-libx265 --enable-libvpx --enable-libtheora --enable-libvorbis --enable-libopus --enable-libass --enable-libwebp --enable-postproc --enable-avresample --enable-libfreetype --enable-openssl --disable-debug libavutil 55. 78.100 / 55. 78.100 libavcodec 57.107.100 / 57.107.100 libavformat 57. 83.100 / 57. 83.100 libavdevice 57. 10.100 / 57. 10.100 libavfilter 6.107.100 / 6.107.100 libavresample 3. 7. 0 / 3. 7. 0 libswscale 4. 8.100 / 4. 8.100 libswresample 2. 9.100 / 2. 9.100 libpostproc 54. 7.100 / 54. 7.100
saudet commented 6 years ago

There is most likely some native dependency missing. There is a cause to that exception, maybe it's not showing up for some reason. Alpine is known to be quite buggy though, so it might take a while to figure out the issue, and even when we do, it probably won't be easy to fix. In any case, please try to load the modules manually and see if we can get any better stack traces:

Loader.load(avutil.class);
Loader.load(swresample.class);
Loader.load(avcodec.class);
chammond75 commented 6 years ago

ok, let me try these commands and see what I can capture. Thank you.

EDIT: I'm assuming these are the classes in org.bytedeco.javacpp and NOT the ones in org.bytedeco.javacpp.presets. Is that correct?

chammond75 commented 6 years ago

Also @saudet is there a recommended version of Linux to use? It may be more feasible for me to switch. In the meantime I'll try to gather the info you requested.

saudet commented 6 years ago

Yes, not the ones in the presets package.

As mentioned here, the binaries are built with CentOS: https://github.com/bytedeco/javacpp-presets#manual-installation

chammond75 commented 6 years ago

Tried loading each of these 3 classes in their own try/catch block (so 3 try/catches in total). avutil and swresample loaded without problem. avcodec did not. Unfortunately there was no more information in the exception than what I've posted before. I'm going to try switching to Centos 7 and see if that can work for me.

chammond75 commented 6 years ago

@saudet switched over to Centos 7 and am STILL getting the same error. I'm at a loss. What can I do!?!?

chammond75 commented 6 years ago

ok, here's what I was able to find:

[root@9a3814890b6e javatmp]# ldd org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57 ldd: warning: you do not have execution permission for `org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57' linux-vdso.so.1 => (0x00007ffd9779e000) libswresample.so.2 => not found libavutil.so.55 => not found libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f13cc6ee000) libm.so.6 => /lib64/libm.so.6 (0x00007f13cc3ec000) libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f13cc0e4000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f13cbee0000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f13cbcca000) libc.so.6 => /lib64/libc.so.6 (0x00007f13cb908000) /lib64/ld-linux-x86-64.so.2 (0x000055f532aea000)

The two missing shared objects are packaged in the jar, however they are not on the system's LD_LIBRARY_PATH. I notice that once I invoke the classes in javacpp a cache directory is created under ~/.javacpp which contains the exploded .so's. If I add that path to my LD_LIBRARY_PATH I see:

[root@c0b299fbec4a javatmp]# ldd /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57 ldd: warning: you do not have execution permission for `/root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57' linux-vdso.so.1 => (0x00007ffd11f59000) libswresample.so.2 => /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libswresample.so.2 (0x00007f8cf4f73000) libavutil.so.55 => /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavutil.so.55 (0x00007f8cf4cfc000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8cf4adc000) libm.so.6 => /lib64/libm.so.6 (0x00007f8cf47da000) libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f8cf44d2000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f8cf42ce000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f8cf40b8000) libc.so.6 => /lib64/libc.so.6 (0x00007f8cf3cf6000) librt.so.1 => /lib64/librt.so.1 (0x00007f8cf3aee000) /lib64/ld-linux-x86-64.so.2 (0x000055f539ec6000)

However just getting ldd working is not sufficient to getting my code to work. I think, in part, because I'm changing my LD_LIBRARY_PATH after the JVM starts. And also because that cache directory is created lazily. So now the challenge is: how do I proactively get these .so's into my LD_LIBRARY_PATH during construction of my Docker image?

Does it sound like I'm on the right track? Any suggestions?

chammond75 commented 6 years ago

Also I noticed this in the properties (this is when running on my Mac where I can step through and debug:

platform.cinclude=[<libavutil/avutil.h>, <libavutil/error.h>, <libavutil/mem.h>, <libavutil/mathematics.h>, <libavutil/rational.h>, <libavutil/log.h>, <libavutil/buffer.h>, <libavutil/pixfmt.h>, <libavutil/frame.h>, <libavutil/samplefmt.h>, <libavutil/channel_layout.h>, <libavutil/cpu.h>, <libavutil/dict.h>, <libavutil/opt.h>, <libavutil/pixdesc.h>, <libavutil/imgutils.h>, <libavutil/downmix_info.h>, <libavutil/stereo3d.h>, <libavutil/ffversion.h>, <libavutil/motion_vector.h>, <libavutil/fifo.h>, <libavutil/audio_fifo.h>, log_callback.h, <libswresample/swresample.h>, <libavcodec/avcodec.h>]}

However log_callback.h is missing on my Linux system. What is the impact of that missing header file?

EDIT: I should add that I copied all of the .so's packaged with the linux-x86_64 jar into my /usr/local/lib directory (so now ldd works) but that still has no resolved the issue. It feels like I just need to get these files into the right location for the library to load them. Any suggestions?

chammond75 commented 6 years ago

Also I added an extra log line to try to get the cause of the exception and it is blank

    try {
        Loader.load(avcodec.class);
    } catch (final Throwable t) {
        logger.error("Problem loading avcodec", t); <-- Prints NoClassDefFoundError
        logger.error("Caused by", t.getCause()); <-- Prints nothing
    }

Do I need to set on of the properties in the properties map to get this library to look in the right place for these shared objects (like "/lib64" instead of "/lib" or "/usr/local/lib")?

saudet commented 6 years ago

None of what you mention is a problem.

Maybe the binaries you have are corrupted. Have you tried to redownload them?

chammond75 commented 6 years ago

I could try to re-download. But can you explain something to me:

It looks like the .so's are loaded as resources from within the jar files (by the class loader) is that right? So then when the classes in the C/C++ layer are initialized where does it search to find the link dependencies? So if libavcodec.so.57 relies on libavutil.so.55 where does it find that dependency? Should it be finding it within the same jar (because that's where it's packaged). Or should it be finding it in ~/.javacpp/cache because that's where the get exploded? Or should it be finding it in $LD_LIBRARY_PATH because that's where libraries get resolved? Or should it be finding it in /lib or /lib64?

Ultimately I'm trying (desperately) to understand the JNI path here. Once Class.forName0() native method is invoked I have no insight into what's happening. So understanding that better, from your perspective, would be very helpful.

Also, what does it say that Loader.load(avutil.class) and Loader.load(swresample.class) work? Should I understand that to mean that libavutil.so.55 and libjniavutil.so as well as libswresample.so and libjniswresample.so are resolving their linker dependencies ok? And that, for some reason, libavcodec.so and libjniavcodec.so are not resolving those dependencies?

Lastly, is there any way to get insight into what exactly is failing inside the native code? Looks like the ClassNotFoundException that is being thrown there is turned into a string which simply says "Could not initialize class org.bytedeco.javacpp.avcodec". Can I get more info? Are there logs somewhere that I should consult? Are there logging properties I should set? Are there system properties I should enable?

Again, any clues would be greatly appreciated. In the meantime I will try re-downloading the jars.

chammond75 commented 6 years ago

Also how concerned should I be about these missing dependencies:

[root@7c2cca9eebf8 lib]# ldd libjniavdevice.so ldd: warning: you do not have execution permission for `./libjniavdevice.so' linux-vdso.so.1 => (0x00007ffdaa9cc000) libavdevice.so.57 => /usr/local/lib/./libavdevice.so.57 (0x00007f8d24c08000) libavfilter.so.6 => /usr/local/lib/./libavfilter.so.6 (0x00007f8d247c2000) libswscale.so.4 => /usr/local/lib/./libswscale.so.4 (0x00007f8d24530000) libpostproc.so.54 => /usr/local/lib/./libpostproc.so.54 (0x00007f8d242e8000) libavformat.so.57 => /usr/local/lib/./libavformat.so.57 (0x00007f8d23cb8000) libavcodec.so.57 => /usr/local/lib/./libavcodec.so.57 (0x00007f8d21dc5000) libswresample.so.2 => /usr/local/lib/./libswresample.so.2 (0x00007f8d21ba8000) libavutil.so.55 => /usr/local/lib/./libavutil.so.55 (0x00007f8d21931000) libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f8d21626000) libm.so.6 => /lib64/libm.so.6 (0x00007f8d21324000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f8d2110d000) libc.so.6 => /lib64/libc.so.6 (0x00007f8d20d4c000) libXfixes.so.3 => not found libXext.so.6 => not found libX11.so.6 => not found libasound.so.2 => not found libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8d20b2e000) libdl.so.2 => /lib64/libdl.so.2 (0x00007f8d2092a000) librt.so.1 => /lib64/librt.so.1 (0x00007f8d20721000) /lib64/ld-linux-x86-64.so.2 (0x000055d8e17c9000)

saudet commented 6 years ago

Like I said, the JDK will tell us what is the cause of the error. The fact that you don't get anything points to a problem with your version of Java or Linux. I can't do anything about that!

To understand more about all this, please go and learn more about shared objects on the Linux platform.

chammond75 commented 6 years ago

@saudet I'm trying to understand how YOUR library is working. I have a working understanding of shared objects on Linux. But I'm asking you to explain how you expect things to work. I honestly don't know how to get the JDK to tell me anything more than I've provided for you. Can you please tell me how to do that? What more do you expect to see? Why, when I try to get the Cause of the exception is it null/empty? What are you expecting the exception from the native code to tell you? Can you please cut/paste examples of other NoClassDefFoundErrors loading avcodec that you've seen? That might at least give me a place to start looking.

Look, I know this is painful and that I'm taxing you with all these questions. But can you see how frustrating this is from my perspective. The person who, presumably, knows that most about this code and this setup is not being terribly responsive. I want to collaborate with you. I want to provide you with whatever information I can to help us debug this together. Pointing me back at the internet to learn about shared objects is not productive. How can we move forward here?

saudet commented 6 years ago

Here's the kind of stack trace you're supposed to get: https://github.com/bytedeco/javacpp-presets/wiki/Debugging-UnsatisfiedLinkError-on-Windows

You can try to set LD_LIBRARY_PATH before launching the JDK, but that won't help, because that's not where the problem is: avutil loads fine for example.

If you want to figure out what the problem is, first figure out why you're not getting this info from the JDK! Fiddling with .so files probably won't help.

chammond75 commented 6 years ago

Thank you @saudet. Can you please explain, though, why I'm seeing a NoClassDefFoundError rather than an UnSatisfiedLinkeError? And how are those things different? It seems like the latter is thrown because a shared object simply isn't in the path. I think in this case all the shared objects are there, but the invocation of the avcodec native class is blowing up for some reason.

saudet commented 6 years ago

Maybe we're not getting an UnsatisfiedLinkError as the cause, maybe that's the point. That's what I'm saying we need to know. You could try to consult upstream with the authors of the JDK!

saudet commented 6 years ago

One thing that might help is setting the "org.bytedeco.javacpp.logger.debug" system property to "true". That will print out what the Loader is doing...

chammond75 commented 6 years ago

In the example you listed here's the stack:

java.lang.UnsatisfiedLinkError: no jniFlyCapture2 in java.library.path

Caused by: java.lang.UnsatisfiedLinkError: So are you surmising that my stack should be: java.lang.NoClassDefFoundError: Caused by: java.lang.UnsatisfiedLinkError: ? Notice that my stack is completely different from the one listed in your post. Note that the at the top of my stack is Class.forName0(). So what, I believe, is happening, is that we are newing a class in libavcode.so (via libjniavcodec.so) and that class is referencing other things that are not present OR it's blowing up due to memory or something else. In any case let me try setting the system property that you just mentioned. Also if you have any thoughts on the afore mentioned unsatisfied dependencies that I mentioned that would be helpful as well. Again, thank you.
chammond75 commented 6 years ago

With debug logging:

 01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libavutil.so.55  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavutil.so.55  01:30:22 Creating symbolic link /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavutil.so  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniavutil.so  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libjniavutil.so  01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Loading class org.bytedeco.javacpp.swresample  01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Loading class org.bytedeco.javacpp.swresample  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libswresample.so.2  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libswresample.so.2  01:30:22 Creating symbolic link /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libswresample.so  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniswresample.so  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libjniswresample.so  01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Loading class org.bytedeco.javacpp.swresample  01:30:22 Loading class org.bytedeco.javacpp.avcodec  01:30:22 Loading class org.bytedeco.javacpp.avutil  01:30:22 Loading class org.bytedeco.javacpp.swresample  01:30:22 Loading class org.bytedeco.javacpp.avcodec  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavcodec.so.57  01:30:22 Creating symbolic link /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libavcodec.so  01:30:22 Locking /root/.javacpp/cache  01:30:22 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniavcodec.so  01:30:22 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libjniavcodec.so  01:30:22 Error loading class org/bytedeco/javacpp/Loader.  01:30:24 Loading class org.bytedeco.javacpp.avutil  01:30:24 Loading class org.bytedeco.javacpp.avutil  01:30:24 Loading class org.bytedeco.javacpp.swresample  01:30:24 Loading class org.bytedeco.javacpp.avutil  01:30:24 Loading class org.bytedeco.javacpp.swresample  01:30:24 Loading class org.bytedeco.javacpp.avcodec  01:30:24 2017-11-18T01:30:24,091 | com_roku_bif_video_processing-worker | ERROR | HLSImageSupplier:101 | Problem loading avcodec  01:30:24 java.lang.NoClassDefFoundError: Could not initialize class org.bytedeco.javacpp.avcodec  01:30:24 at java.lang.Class.forName0(Native Method) ~[?:1.8.0_45]  01:30:24 at java.lang.Class.forName(Class.java:348) ~[?:1.8.0_45]  01:30:24 at org.bytedeco.javacpp.Loader.load(Loader.java:739) ~[javacpp-1.3.3.jar:1.3.3]  01:30:24 at org.bytedeco.javacpp.Loader.load(Loader.java:700) ~[javacpp-1.3.3.jar:1.3.3]  01:30:24 at org.bytedeco.javacpp.Loader.load(Loader.java:684) ~[javacpp-1.3.3.jar:1.3.3]  01:30:24 at org.bytedeco.javacpp.avformat$AVFormatContext.(avformat.java:2819) ~[ffmpeg-3.2.1-1.3.jar:1.3.3]  01:30:24 at org.bytedeco.javacv.FFmpegFrameGrabber.startUnsafe(FFmpegFrameGrabber.java:509) ~[javacv-1.3.3.jar:1.3.3]  01:30:24 at org.bytedeco.javacv.FFmpegFrameGrabber.start(FFmpegFrameGrabber.java:503) ~[javacv-1.3.3.jar:1.3.3]

My code after this!

    try {
        grabber.start();
        Frame f = null;
        while ((f = grabber.grabKeyFrame()) != null) {
            final BufferedImage image = converter.convert(f);
            final Double timestamp = Double.valueOf(grabber.getTimestamp() / 1_000_000d);
            holder.collectImage(image, timestamp);
        }
    } catch (final IOException e) {
        logger.warn("IOException during frame grabbing", e);
    } finally {
        try {
            grabber.close();
        } catch (final Exception e) {
            logger.warn("Exception closing frame grabber", e);
        }
    }
saudet commented 6 years ago

It's failing on a very simple call to get a reference to the Loader in native code: https://github.com/bytedeco/javacpp/blob/master/src/main/java/org/bytedeco/javacpp/tools/Generator.java#L687

Have you tried to change the version of your JDK? If you're stuck with a specific vendor and/or version, then please contact the vendor of your JDK. This doesn't look like a problem with JavaCPP, Linux, or FFmpeg.

chammond75 commented 6 years ago

Is there a recommended version of the JDK? I can try updating.

Just so I understand then. The root problem is this: Error loading class org/bytedeco/javacpp/Loader.

And that is, in turn, leading to a failure to load avcodec.class? But not leading to a failure to load avutil.class or swresample.class. Is that correct?

Put another way: Why does the Loader class only fail to load AFTER jniavcodec is extracted and loaded?

02:16:06 Locking /root/.javacpp/cache  02:16:06 Extracting jar:file:/usr/bifservice/lib/ffmpeg-3.2.1-1.3-linux-x86_64.jar!/org/bytedeco/javacpp/linux-x86_64/libjniavcodec.so  02:16:06 Loading /root/.javacpp/cache/ffmpeg-3.2.1-1.3-linux-x86_64.jar/org/bytedeco/javacpp/linux-x86_64/libjniavcodec.so  02:16:06 Error loading class org/bytedeco/javacpp/Loader.  02:16:08 Loading class org.bytedeco.javacpp.avutil  02:16:08 Loading class org.bytedeco.javacpp.swresample  02:16:08 Loading class org.bytedeco.javacpp.avcodec

chammond75 commented 6 years ago

@saudet btw, thank you for the code link. What does this mean:

jclass cls = env->FindClass(JavaCPP_classNames[i]);"); out.println(" if (cls == NULL || env->ExceptionCheck())

that is, under what conditions would "cls" be null or env->ExceptionCheck() be true? Could there be some underlying system constraint issue?

saudet commented 6 years ago

Possibly, never heard of anyone with that issue though.

chammond75 commented 6 years ago

Ok, I got it that you've not seen this problem before. However, not having seen it before is not a solution and, unfortunately, I need a solution. So, under what condition would env->FindClass return null?

saudet commented 6 years ago

https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#FindClass

chammond75 commented 6 years ago

Ok, thanks @saudet I'll take a look at that. In the meantime can you answer this question for me:

I see that avutil, avcodec, and swresample get reloaded every time one of the jars is extracted and loaded. I'm assuming each of those involves an invocation of the Loader class. Is that correct? If so, can you speculate as to what is special about the case where libjniavcodec is extracted and loaded? What I'm getting at is: Is there still potentially a problem with libavcodec and/or one of its dependencies? And could that problem be the cause of the failure to load the Loader class? Or are the two things coincidences?

saudet commented 6 years ago

Might be related to this: https://github.com/bytedeco/javacv/issues/791

chammond75 commented 6 years ago

This seems promising. I will try it first thing tomorrow morning. Thank you.

chammond75 commented 6 years ago

Tried increasing the stack size to 1mb and that still didn't work. Also set the number of shadow pages to 20 and that didn't help either. ::sigh::

wongjoel commented 6 years ago

May not be terribly helpful, but could you tell us what Java runtime you are currently using for completeness sake? (I think java --version should give enough info)

chammond75 commented 6 years ago

From the docker file:

ENV JDK_URL http://download.oracle.com/otn-pub/java/jdk/8u91-b14/jdk-8u91-linux-x64.rpm ENV JDK_RPM jdk-8u91-linux-x64.rpm'

Does that help?

saudet commented 6 years ago

I use OpenJDK 8, whatever version works fine. Oracle JDK 8 also works fine, obviously.

Docker containers come with weird bugs and limits. I'd check that first.

chammond75 commented 6 years ago

I'm attempting to get a setup running outside of Docker. Again, to reiterate, this works just fine on my local Mac OS X. I don't think it's a Docker issue. I really think that there is a missing "Caused By" here and that Caused By will probably tell me that the .so's that I have are not internally consistent. That's the only thing I can think of. Like I said, I tried increasing the stack space and the shadow page space. But to me this feels like the init of the avcodec class is invoking something in libavcodec that is not finding what it needs elsewhere (even though ldd says that all the dependencies are satisfied). Also, in one of my earlier notes I included that the following dependencies were missing:

libXfixes.so.3 => not found libXext.so.6 => not found libX11.so.6 => not found libasound.so.2 => not found

Not sure how important those are. That came from checking "ldd libjniavdevice.so" which seems like it gets loaded AFTER avcodec. So not sure how relevant that is (yet?).

saudet commented 6 years ago

This change might help: https://github.com/bytedeco/javacpp/commit/79680934375a4844d64a026d9b02e58196915c7f

chammond75 commented 6 years ago

Great, how could I test that out?

saudet commented 6 years ago

Use the 1.3.4-SNAPSHOT artifacts: http://bytedeco.org/builds/

chammond75 commented 6 years ago

Ok, I haven't tried the snaphshot yet. But I DO HAVE IT WORKING on a Centos 7 Docker image! I had previously got it working on a Centos 7 VM using Vagrant. I noticed that my max heap was set to 1Gb. That resulted in a bunch of OOM errors that did not make it to my logs in AWS but were on the console. So I increased my Docker memory requirement and max heap both to 3Gb. I also followed the advice of one of the other issues mentioned earlier and bumped up my stack size (-Xss2m) as well as set the shadow page size to 20. With these settings I now get the output that I expect! I do see some debug messages from javacpp saying that libXfixes.so is missing. But that doesn't seem to affect my output. In any case this is great and gives me a path forward. At some point in the future I'll try returning to Alpine Linux with the afore mentioned settings and see if that works as well.

Thanks for your help on this.

saudet commented 6 years ago

1 GB is pretty small, so you were just running out of memory it seems.

In any case, great to hear it's working well now!

saudet commented 1 year ago

Duplicate of https://github.com/bytedeco/javacpp-presets/issues/1379