Running CUDA through JNI can't find CUDA variables when linked...

I’ve been trying to restructure some generic applications to run hotspots on CUDA. However, I can’t seem to get Java to run the CUDA functions. Regular JNI calls work, and so do regular CUDA applications, so I don’t see why this should be impossible.

OS/Java/CUDA Info:
OS: Linux Ver: 2.6.20-17-generic (Ubuntu)
OS Architecture: amd64
JRE: Java™ SE Runtime EnvironmentVer: 1.6.0
JVM: Java HotSpot™ 64-Bit Server VM Ver: 1.6.0-b105
CUDA ver. 1.1

Here is what I’m attempting to compile a simple cu file to run with Java:

nvcc -I"/usr/lib/jvm/java-6-sun-1.6.0.00/include" -I"/usr/lib/jvm/java-6-sun-1.6.0.00/include/linux" -c CUDATest.cu -o CUDATest.o -Xcompiler -fPIC
ld -shared CUDATest.o -o libCUDATest.so (or: gcc -shared CUDATest.o -o libCUDATest.so)

Running it:

java CUDATest

Here is the error I’m getting:

java: error: symbol lookup error: /home/xxxxxx/JNI/libCUDATest.so: undefined symbol: _Znam
(get a slightly different error with gcc but the same idea is there, unresolved symbols)

I was wondering if anyone can help me figure this out. I’m at the end of my rope trying to figure this out. If any more information is needed I would be happy to supply it. Thanks…

are you using extern “C” around your functions?

I know JNI + CUDA works, as I’ve done some basic experiments with it, although be warned–you may need a one-line patch to zlib to deal with a bug when you have two conflicting versions of the library being loaded (Java has/had a statically linked zlib, CUDA loaded the system’s libz, there’s a mismatch, and there’s a segfault associated with it).

Try using g++ to link your shared library (g++ --shared …).

You are just using ld and the c++ libraries are not getting included.

_Znam is “operator new(unsigned long)”.

[i]are you using extern “C” around your functions?

I know JNI + CUDA works, as I’ve done some basic experiments with it, although be warned–you may need a one-line patch to zlib to deal with a bug when you have two conflicting versions of the library being loaded (Java has/had a statically linked zlib, CUDA loaded the system’s libz, there’s a mismatch, and there’s a segfault associated with it).[/i]

Well the function is declared as an extern C function in the header created with javah. What is this patch you are talking about?

[i]
Try using g++ to link your shared library (g++ --shared …).

You are just using ld and the c++ libraries are not getting included.

_Znam is “operator new(unsigned long)”.[/i]

Using g++ gives me the same error as if I tried to link with gcc. Here is the error:

error: Exception in thread “main” java.lang.UnsatisfiedLinkError:
/home/xxxxxx/JNI/libCUDATest.so: /home/xxxxxx/JNI/libCUDATest.so: undefined symbol:
__cudaUnregisterFatBinary
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1676)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1030)
at CUDATest.(CUDATest.java:14)
(then hangs and I have to kill the process)

Make sure you link CUDA libraries when you link your library:

-L $(CUDA_INSTALL_PATH)/lib -lcuda -lcudart

And keep using g++ to link, since it looks like you got past the original undefined symbol, am I right?

Also you can check your libCUDATest.so for undefined symbols by doing:

ldd -r libCUDATest.so

I’ve figured it out. There were two things I was doing wrong. One was I was using the new and delete operator, which is C++ code. I replaced those with calloc and free. That actually may still work, but I’m sticking with just using C code to save myself the hassle.

Thank you so much icegibbon! I was missing linking the CUDA libraries. I ended up just using ld instead of g++ as well. Either way, your posts were very helpful and helped me located the problem.