2

I am trying to call a C++ library from java side and have written necessary jni code. However, when my java code tries to load my C++ library via System.loadLibrary, it complains the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: libmylib.so: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by libmylib.so)

I later found that it is because I have two different GLIBC versions on my system, and the default one is the older one, while libmylib.so is required to built from the newer GLIBC. As a result, java links to the wrong GLIBC.

I tried the following things, but it does not work :(.

The first one is to try to load correct library manually via System.load in my java code. Specifically, I added the following codes before it loads my library:

static {
  System.load("/usr/local/gcc-4.8.1-glibc-2.17/lib/libc.so.6");
  System.load("/usr/local/gcc-4.8.1-glibc-2.17/lib/libstdc++.so.6.0.18");      
  System.loadLibrary(mylib);
}

The libc.so.6 is also added because libstdc++ depends on it (otherwise java will load the wrong libc and complains another error). However, this time java complains the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError:
  /usr/local/gcc-4.8.1-glibc2.17/lib/libc-2.17.so:
      __vdso_time: invalid mode for dlopen(): Invalid argument

And this error is caused by mixing two versions of GLIBC as described in this question. The solution to that question is for building C++ program with -Wl,--dynamic-linker set properly (also described here). However, I don't know how to do that in Java.

I tried to set LD_LIBRARY_PATH to the newer version, but the situation is just the same :(.

Can I know how to make java link to the correct library?

(PS: a solution without make install newer version of glibc is preferred, since many other applications in my machine rely on the current default glibc)

I have been searching and trying solutions to my problem for days, but none of them succeed :(

Stackoverflow, you're my only hope :~.

jww
  • 97,681
  • 90
  • 411
  • 885
keelar
  • 5,814
  • 7
  • 40
  • 79
  • "I tried to set LD_LIBRARY_PATH to the newer version," How did you do that? – Lee Duhem Mar 21 '14 at 05:35
  • Not sure if I did this right. I tried that by `export LD_LIBRARY_PATH=path_to_new_glib`, and also tried to do `java -Djava.library.path=path_to_new_glib`, but both complain the same `__vdso_time: invalid mode for dlopen(): Invalid argument` error. – keelar Mar 21 '14 at 05:41
  • I guess that error message means your setting of `LD_LIBRARY_PATH` is effective. – Lee Duhem Mar 21 '14 at 05:50
  • I think so, but that error seems to be mixing two libraries together as the linked question suggests (the first question link also says simply changing LD_LIBRARY_PATH will produce this error.) Do you have any idea on this? – keelar Mar 21 '14 at 05:54
  • I think you should rebuild your `libmylib.so` to use the default Glibc in your system. This would be the simplest solution to your problem. – Lee Duhem Mar 21 '14 at 05:56
  • But the default one does not support `-std=c++11` while my library requires that :(. – keelar Mar 21 '14 at 06:02
  • Then you are in a much biger trouble. The reason of your problem is that the dynamic linker your program (maybe `java`) use does not match the `libc.so` it tries to load. – Lee Duhem Mar 21 '14 at 06:19
  • Do you have any idea on how to make java to use the correct glib? even I manually force java to load the correct libc.so, it will still try to load other libraries from the incorrect glib :( – keelar Mar 21 '14 at 06:21
  • 1
    The path of dynamic linker is hard coded in executable, that is the problem. – Lee Duhem Mar 21 '14 at 06:24
  • By hard coded in executable, can I know which executable you refer to? is it the way I build my library wrong? or the executable is java? – keelar Mar 21 '14 at 06:35
  • 1
    In your case, I guess the executable is `java` itself. When `java` tries to load a dynamic library, it may use `dlopen()`, and it will use the same dynamic linker as the `java` using. – Lee Duhem Mar 21 '14 at 06:38

2 Answers2

4

System.load("/usr/local/gcc-4.8.1-glibc-2.17/lib/libc.so.6");

As I explained here, this can not possibly work.

By the time you reach above statement, the system libc.so.6 has already been loaded (at process startup), and you absolutely can not have two versions of libc.so.6 loaded into the same process.

Community
  • 1
  • 1
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
0

Try using LD_PRELOAD=new_c_library.so java -javastuff

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131
  • Still encounter the same problem :~~ `java: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument`. Did I do something wrong? – keelar Mar 21 '14 at 17:57
  • I wish people would stop suggesting `LD_PRELOAD` of `libc.so.6`. Just think about *which* code interprets `LD_PRELOAD` (hint: that code is in libc!). – Employed Russian Mar 22 '14 at 16:08
  • @EmployedRussian: Isn't ld-linux.so built static? It's the dynamic linker, it can't require itself to run. Therefore, it shouldn't be pulling in libc symbols. – Zan Lynx Mar 22 '14 at 16:53
  • 1
    "Isn't ld-linux.so static" -- it's *complicated*. No, it is not completely static, as you can see by running `readlink -d ld-linux.so.2`. It also *does* pull `libc.so.6` symbols, as can be observed by running a binary under GDB, setting `catch syscall mmap64`, and looking at stack -- the first few calls will be executed by `ld-linux` directly, but subsequent calls will go through `libc.so.6`. – Employed Russian Mar 22 '14 at 17:34
  • @EmployedRussian: Its possible that it has changed, or options are different or something, but when I was doing a lot of Gentoo building in 2008 I am almost entirely certain ld-linux.so was static and didn't load anything. Because PRELOAD worked for me. – Zan Lynx Mar 23 '14 at 05:39