Just a simple question: Is it possible to call a java function from c/c++ ?
7 Answers
Yes you can, but it is a little convoluted, and works in a reflective/non type safe way (example uses the C++ api which is a little cleaner than the C version). In this case it creates an instance of the Java VM from within the C code. If your native code is first being called from Java then there is no need to construct a VM instance
#include<jni.h>
#include<stdio.h>
int main(int argc, char** argv) {
JavaVM *vm;
JNIEnv *env;
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.nOptions = 0;
vm_args.ignoreUnrecognized = 1;
// Construct a VM
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
// Construct a String
jstring jstr = env->NewStringUTF("Hello World");
// First get the class that contains the method you need to call
jclass clazz = env->FindClass("java/lang/String");
// Get the method that you want to call
jmethodID to_lower = env->GetMethodID(clazz, "toLowerCase",
"()Ljava/lang/String;");
// Call the method on the object
jobject result = env->CallObjectMethod(jstr, to_lower);
// Get a C-style string
const char* str = env->GetStringUTFChars((jstring) result, NULL);
printf("%s\n", str);
// Clean up
env->ReleaseStringUTFChars(jstr, str);
// Shutdown the VM.
vm->DestroyJavaVM();
}
To compile (on Ubuntu):
g++ -I/usr/lib/jvm/java-6-sun/include \
-I/usr/lib/jvm/java-6-sun/include/linux \
-L/usr/lib/jvm/java-6-sun/jre/lib/i386/server/ -ljvm jnitest.cc
Note: that the return code from each of these methods should be checked in order to implement correct error handling (I've ignored this for convenience). E.g.
str = env->GetStringUTFChars(jstr, NULL);
if (str == NULL) {
return; /* out of memory */
}

- 14,153
- 4
- 48
- 55
-
1+1 for example. Might also want to include links/examples of setting up the headers, function signatures, etc? – poundifdef Jun 14 '09 at 16:25
-
your solution is great but what how to load or set classpath that we created For example HelloWorld.java i.e `env->FindClass("HelloWorld");` – Deepak Kumar Jan 18 '17 at 12:15
-
1This worked for me, thank goodness. I upvoted, and let me just mention that I used "-Wl,-rpath,${lib_dir}", without quotes of course, where lib_dir is the directory where libjvm.so lies (I used 'find /usr/lib/jvm/ -name "libjvm.so"', and took the dirname for the actual jvm lib directory in my environment). The -Wl,-rpath,${lib_dir} in the link (or compile/link) step (i.e. g++) makes it so you don't have to specify lib_dir in LD_LIBRARY_PATH at runtime. – davernator Sep 19 '18 at 19:13
Yes it is, but you have to do it via JNI: http://java.sun.com/javase/6/docs/technotes/guides/jni/index.html

- 755,051
- 104
- 632
- 656
-
3I've seen JNI used to call C++ from Java. Didn't know it worked the other way as well. – Kieveli Jun 14 '09 at 13:35
-
4Strange, I've always seen it more commonly used to provide access to C++ libraries from Java, but it works both ways. – CB Bailey Jun 14 '09 at 13:38
-
1@CBBailey "provide access to C++ libraries from Java" means "call C++ from Java". No? I feel like you're both saying the same thing: "Commonly used to call [C++ code] from Java". – Aykhan Hagverdili Aug 01 '20 at 19:07
Take a look at the invocation API. This enables you to load and start up a JVM from within your native application, and then to invoke methods upon it from the application.
Briefly (from the linked doc)
/* load and initialize a Java VM, return a JNI interface
* pointer in env */
JNI_CreateJavaVM(&jvm, &env, &vm_args);
/* invoke the Main.test method using the JNI */
jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
env->CallStaticVoidMethod(cls, mid, 100);

- 268,207
- 37
- 334
- 440
The following function allows you to create the VM.
JNIEnv* create_vm(JavaVM ** jvm)
{
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[2];
options[0].optionString = "-Djava.class.path=.";
options[1].optionString = "-DXcheck:jni:pedantic";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 2;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE; // remove unrecognized options
int ret = JNI_CreateJavaVM(jvm, (void**) &env, &vm_args);
if (ret < 0) printf("\n<<<<< Unable to Launch JVM >>>>>\n");
return env;
}
Compile the famous Hello World program. The following function attempts to call the main method of the HelloWorld Program.
int main(int argc, char* argv[])
{
JNIEnv* env;
JavaVM* jvm;
env = create_vm(&jvm);
if (env == NULL) return 1;
jclass myClass = NULL;
jmethodID main = NULL;
myClass = env->FindClass("HelloWorld");
if (myClass != NULL)
main = env->GetStaticMethodID(myClass, "main", "([Ljava/lang/String;)V");
else
printf("Unable to find the requested class\n");
if (main != NULL)
{
env->CallStaticVoidMethod( myClass, main, " ");
}else printf("main method not found") ;
jvm->DestroyJavaVM();
return 0;
}
Now put create_vm function and main function into a single cpp file, include jni.h and compile it. I used MinGW on windows.
g++ -D_JNI_IMPLEMENTATION_ -I"C:\Program Files\Java\jdk1.6.0_32\include" -I"C:\Program Files\Java\jdk1.6.0_32\include\win32" hello.cpp -L"C:\Program Files\Java\jre6\bin\client" -ljvm -o hello.exe
Exection
Now if you run the created exe, you will get an error. jvm.dll not found .
Put C:\Program Files\Java\jre6\bin\client
in your PATH environment variable. Now you can
run the exe file.
Note: Don't displace the jvm.dll file.

- 9,704
- 6
- 64
- 74
Yes, you can call a Java function from C++ or C, but unless you're using something like COM or CORBA (or another 3rd-party tool that I'm probably not aware of) you'll have to do this in the context of JNI.
The whole procedure to call a Java method from native code is described in Chapter 4 in section 4.2 called "Calling Methods" in Sun's JNI guide pdf, which you can find here.

- 47,427
- 17
- 69
- 97

- 24,095
- 5
- 52
- 70
After coding above examples, you need to do some configuration on your project.
Steps to link the jvm.lib to your project in Visual Studio:
- Right click on the project -> properties.
- On the Properties dialog box, add jvm.lib under Linker->Input->AdditionalDependencies area.
- Lastly write jvm.lib path(like "C:\Program Files\Java\jdk1.7.0_60\lib") under Linker->General->AdditionalLibraryDirectories
After those steps, your project can link to jvm and work well.

- 1,292
- 19
- 24