question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

JDK system dependency: link against libjvm

See original GitHub issue

Describe the bug jni.h does not only contain structures to run c(++) code from java, but also java from c(++). For this to work the resulting binary has to be linked against libjvm.so located in $JAVA_HOME/lib/server/. Otherwise if your code tries to call these, the linker will fail:

FAILED: mjvmtest 
cc  -o mjvmtest mjvmtest.p/jvm.c.o -Wl,--as-needed -Wl,--no-undefined
/usr/lib64/gcc/x86_64-suse-linux/11/../../../../x86_64-suse-linux/bin/ld: mjvmtest.p/jvm.c.o: in function `main':
/home/admin/workspace/cli/meson/mjvmtest/_build/../jvm.c:16: undefined reference to `JNI_CreateJavaVM'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

To Reproduce I’ve taken the JNI Invokation Example: https://docs.oracle.com/en/java/javase/11/docs/specs/jni/invocation.html, ported it to C and made it actually do something.

#include <jni.h>	/* where everything is defined */
#include <stdbool.h>

int main(int, char**) {
	JavaVM *jvm;	/* denotes a Java VM */
	JNIEnv *env;	/* pointer to native method interface */
	JavaVMInitArgs vm_args;	/* JDK/JRE 10 VM initialization arguments */
	JavaVMOption options[2];
	options[0].optionString = "-Djava.class.path=/usr/lib64/java";
	options[1].optionString = "-Xcheck:jni";
	vm_args.version = JNI_VERSION_10;
	vm_args.nOptions = 1;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = false;
	/* load and initialize a Java VM, return a JNI interface
	* pointer in env */
	JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
	/* get stdout PrintStream */
	jclass system = (*env)->FindClass(env, "java/lang/System");
	jfieldID jstdout_id = (*env)->GetStaticFieldID(env, system, "out", "Ljava/io/PrintStream;");
	jobject jstdout = (*env)->GetStaticObjectField(env, system, jstdout_id);
	/* invoke println method of PrintStream */
	jclass print_stream = (*env)->FindClass(env, "java/io/PrintStream");
	jmethodID mid = (*env)->GetMethodID(env, print_stream, "println", "(Ljava/lang/String;)V");
	jstring to_print = (*env)->NewStringUTF(env, "Hello World from C");
	(*env)->CallVoidMethod(env, jstdout, mid, to_print);
	/* We are done. */
	(*jvm)->DestroyJavaVM(jvm);
}
project('mjvmtest', 'c',
	version : '0.1',
	default_options : ['warning_level=3', 'c_std=gnu2x'])

app = executable('mjvmtest', [
		'jvm.c'
	],
	dependencies: [
		#dependency('jdk', version: ['>=11', '<12'])
		dependency('jdk', version: '>=11')
	],
	install : true
)

Expected behavior I expect it to link against libjvm.so.

Adding self.link_args = [f'{self.java_home}/lib/server/libjvm.so']to the JDKSystemDependency init method in mesonbuild/depenencies/dev.py makes it work.

What needs to be done is to extend it that it uses the correct file extension for each OS and maybe link it in a way that libjvm.so does not have to be in the library search path.

system parameters

  • OS: openSUSE Tumbleweed 20211117
  • Python 3.8.12
  • Meson 0.59.4 & cc80187
  • Ninja 1.10.2

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:11 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
tristan957commented, Mar 1, 2022

I would assume one use case for this is embedding a JVM in another application. Thanks. I will switch to modules. The default behavior would stay as “just add the include directories” since most people probably aren’t linking to the JVM libraries.

0reactions
tristan957commented, Mar 1, 2022

Right. Information around this is pretty hard to come by to be honest. Will have a PR up in a bit

Read more comments on GitHub >

github_iconTop Results From Across the Web

Linking JNI code with the JVM - java - Stack Overflow
I have a Java program from which I load a JNI library. Can that JNI library be linked to HotSpot's libjvm.so shared library,...
Read more >
Make Java shared libraries like libjvm.so available for linking
This needs to link against a libjvm.so. Currently it does: $ readelf --dynamic ./usr/lib64/libmesos-0.18.0.so.0 | grep jvm 0x0000000000000001 (NEEDED) Shared ...
Read more >
Symbolic link error to Java / LIBJVM - Ask Ubuntu
I think this is bad...but thought I'd reach out in case there was a way to fix it. Any thoughts appreciated! Ubuntu 12.04....
Read more >
Java JDK missing libjli.so path in dependency list, Debian
It's supposed to work out of the box - with no messing with /etc/ld.so.conf* or ldconfig - and it can easily do so....
Read more >
C/C++ Unable to link with JVM library - Gradle Forums
As part of the compiler args, I've included the full path to libjvm.so /* * libhbase_test executable */ executables { libhbase_test ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found