Skip to content

Instantly share code, notes, and snippets.

@shannah
Created January 19, 2022 20:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shannah/b9a02017acbefad795639f612ad34a1d to your computer and use it in GitHub Desktop.
Save shannah/b9a02017acbefad795639f612ad34a1d to your computer and use it in GitHub Desktop.
#ifdef LINK_JVM
#ifndef jvm_h
#define jvm_h
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
char* copyString(const char* s)
{
const char* p1;
char *s2, *p2;
s2 = (char*)malloc(strlen(s));
p1 = s;
p2 = s2;
// Executing till the null
// character is found
while (*p1 != '\0') {
// Copy the content of s1 to s2
*p2 = *p1;
p1++;
p2++;
}
*p2 = '\0';
return s2;
}
void myCustomFunc() {
printf("In my customFunc\n");
fflush(stdout);
}
const char* JDEPLOY_JVM_MAINCLASS;
const char* JDEPLOY_JVM_CLASSPATH;
const char* JDEPLOY_JVM_ARGSTRING;
//int _client4jRunJar(const char* mainClass, const char* classPath, const char* argsString) {
void* _client4JRunJar(void* p) {
const char* mainClass = JDEPLOY_JVM_MAINCLASS;
const char* classPath = JDEPLOY_JVM_CLASSPATH;
const char* argsString = JDEPLOY_JVM_ARGSTRING;
printf("In C client4jRunJar\n");
JavaVM *vm = NULL;
JNIEnv *env = NULL;
JavaVMInitArgs vm_args;
char* ptr = strtok(copyString(argsString), "\n");
int numOptions = 0;
printf("About to count options ... %s \n", ptr);
while (ptr != NULL) {
printf("Tok is %s\n", ptr);
if (strlen(ptr) >= 2 && strncmp("-D", ptr, 2) == 0) {
numOptions++;
} else if (strlen(ptr) >= 5 && strncmp("-jar ", ptr, 5) == 0) {
// This will translate into -Djava.class.path
numOptions++;
} else if (strlen(ptr) >= 2 && strncmp("-X", ptr, 2) == 0) {
numOptions++;
}
printf("About to fetch next token\n");
ptr = strtok(NULL, "\n");
printf("Fetched next token complete \n");
}
numOptions++; // for the -Djava.class.path
printf("Found options\n");
JavaVMOption options[16];
int optionIndex = 0;
ptr = strtok(copyString(argsString), "\n");
while (ptr != NULL) {
if (strlen(ptr) >= 2 && strncmp("-D", ptr, 2) == 0) {
options[optionIndex].optionString = ptr;
optionIndex++;
} else if (strlen(ptr) >= 5 && strncmp("-jar ", ptr, 5) == 0) {
// This will translate into -Djava.class.path
optionIndex++;
} else if (strlen(ptr) >= 2 && strncmp("-X", ptr, 2) == 0) {
options[optionIndex].optionString = ptr;
optionIndex++;
}
ptr = strtok(NULL, "\n");
}
printf("Finished parsing options\n");
char classPathFlag[4096] = "-Djava.class.path=";
//strcat(classPathFlag, jarRunnerPath);
strcat(classPathFlag, classPath);
printf("Classpath: %s\n", classPathFlag);
options[optionIndex].optionString = classPathFlag;
vm_args.version = JNI_VERSION_1_8;
vm_args.options = options;
vm_args.nOptions = numOptions;
vm_args.ignoreUnrecognized = 1;
jobjectArray args;
printf("About to launch java VM\n");
jint res = JNI_CreateJavaVM(&vm, (void **)&env, &vm_args);
if (res < 0) {
printf("Can't create Java VM\n");
exit(1);
}
printf("Looking for main class\n");
jclass cls = (*env)->FindClass(env, mainClass);
if (cls == 0) {
printf("Main class %s class not found\n", mainClass);
exit(1);
}
jmethodID mid =
(*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
if (mid == 0) {
printf("main() method not found\n");
exit(1);
}
//jstring argString = (*env)->NewStringUTF(env, ""); //empty arg list
args =
(*env)->NewObjectArray(env, 0, (*env)->FindClass(env, "java/lang/String"), NULL);
if (args == 0) {
printf("Out of memory\n");
exit(1);
}
printf("Calling main() method...\n");
(*env)->CallStaticVoidMethod(env, cls, mid, args);
(*vm)->DestroyJavaVM(vm);
}
int client4jRunJar(const char* mainClass, const char* classPath, const char* argsString) {
JDEPLOY_JVM_MAINCLASS=mainClass;
JDEPLOY_JVM_CLASSPATH=classPath;
JDEPLOY_JVM_ARGSTRING=argsString;
if (1) {
_client4JRunJar(NULL);
return 1;
}
pthread_t thread1;
int iret1;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, _client4JRunJar, NULL);
/* Wait till threads are complete before main continues. Unless we */
/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
printf("Thread 1 returns: %d\n",iret1);
return iret1;
}
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment