Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

java.lang.NoClassDefFoundError running javacpp on Linux #832

Closed
chammond75 opened this issue Nov 16, 2017 · 40 comments
Closed

java.lang.NoClassDefFoundError running javacpp on Linux #832

chammond75 opened this issue Nov 16, 2017 · 40 comments

Comments

@chammond75
Copy link

chammond75 commented Nov 16, 2017

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
Copy link
Member

saudet commented Nov 16, 2017

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
Copy link
Author

chammond75 commented Nov 16, 2017

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
Copy link
Author

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
Copy link
Member

saudet commented Nov 16, 2017

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
Copy link
Author

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
Copy link
Author

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

@chammond75
Copy link
Author

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
Copy link
Author

chammond75 commented Nov 17, 2017

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
Copy link
Author

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
Copy link
Member

saudet commented Nov 17, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Author

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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

@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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Member

saudet commented Nov 18, 2017

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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Author

chammond75 commented Nov 18, 2017

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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

chammond75 commented Nov 18, 2017

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
Copy link
Author

@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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Member

saudet commented Nov 18, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Member

saudet commented Nov 19, 2017 via email

@chammond75
Copy link
Author

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

@chammond75
Copy link
Author

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
Copy link

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
Copy link
Author

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
Copy link
Member

saudet commented Nov 20, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Member

saudet commented Nov 27, 2017

This change might help: bytedeco/javacpp@7968093

@chammond75
Copy link
Author

Great, how could I test that out?

@saudet
Copy link
Member

saudet commented Nov 27, 2017 via email

@chammond75
Copy link
Author

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
Copy link
Member

saudet commented Nov 28, 2017

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
Copy link
Member

saudet commented Jul 22, 2023

Duplicate of bytedeco/javacpp-presets#1379

@saudet saudet marked this as a duplicate of bytedeco/javacpp-presets#1379 Jul 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants