1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  * ORACLE PROPRIETARY/CONFIDENTIAL.  Use is subject to license terms.
   4  */
   5 
   6 #if defined(__sun) && defined(__SVR4)
   7 #define _POSIX_PTHREAD_SEMANTICS
   8 
   9 #include <jni.h>
  10 #include <dlfcn.h>
  11 #include <limits.h>
  12 #include <pthread.h>
  13 #include <signal.h>
  14 #include <errno.h>
  15 #include <stdio.h>
  16 #include <string.h>
  17 
  18 void *handle;
  19 char* error;
  20 char path[PATH_MAX];
  21 
  22 jint(JNICALL *jni_create_java_vm)(JavaVM **, JNIEnv **, void *) = NULL;
  23 
  24 JavaVM *jvm;
  25 
  26 extern void exit(int);
  27 
  28 void loadJVM() {
  29     char lib[PATH_MAX];
  30     sprintf(lib, "%s/lib/sparcv9/server/libjvm.so", path);
  31     handle = dlopen(lib, RTLD_LAZY);
  32     if (!handle) {
  33         fputs(dlerror(), stderr);
  34         fputs(" : 2\n", stderr);
  35         exit(1);
  36     }
  37     fputs("Will load JVM...\n", stderr);
  38 
  39     //find the address of function
  40     *(void **) (&jni_create_java_vm) = dlsym(handle, "JNI_CreateJavaVM");
  41     if ((error = dlerror()) != NULL) {
  42         fputs(error, stderr);
  43         fputs(" : 3\n", stderr);
  44         exit(1);
  45     }
  46 
  47     fputs("JVM loaded okay.\n", stderr);
  48 }
  49 
  50 JNIEnv* initJVM() /* The JDK1.2 way of doing it */ {
  51     JNIEnv *env = NULL;
  52     JavaVMInitArgs vm_args;
  53     JavaVMOption options[1];
  54     jint res;
  55 
  56     /*    options[0].optionString = "-Djava.class.path=."; */ /* user classes */
  57     options[0].optionString = "-Xrs"; /* user classes */
  58 
  59     vm_args.version = JNI_VERSION_1_2;
  60     vm_args.nOptions = 1;
  61     vm_args.options = options;
  62     vm_args.ignoreUnrecognized = JNI_FALSE;
  63 
  64     fputs("Will create JVM...\n", stderr);
  65 
  66     res = (*jni_create_java_vm)(&jvm, &env, &vm_args);
  67     if (res < 0) {
  68         fprintf(stderr, "Can't create Java VM: %d\n", res);
  69         exit(1);
  70     }
  71 
  72     fputs("JVM created OK!\n", stderr);
  73     return env;
  74 }
  75 
  76 void doStuff(JNIEnv *env) {
  77     jclass cls;
  78     jmethodID mid;
  79     jstring jstr;
  80     jobjectArray args;
  81 
  82     cls = (*env)->FindClass(env, "Prog");
  83     if (cls == 0) {
  84         fprintf(stderr, "Can't find Prog class\n");
  85         exit(1);
  86     }
  87 
  88     mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
  89     if (mid == 0) {
  90         fprintf(stderr, "Can't find Prog.main\n");
  91         exit(1);
  92     }
  93 
  94     jstr = (*env)->NewStringUTF(env, "from C!");
  95     if (jstr == 0) {
  96         fprintf(stderr, "Out of memory\n");
  97         exit(1);
  98     }
  99     args = (*env)->NewObjectArray(env, 1,
 100             (*env)->FindClass(env, "java/lang/String"), jstr);
 101     if (args == 0) {
 102         fprintf(stderr, "Out of memory\n");
 103         exit(1);
 104     }
 105     (*env)->CallStaticVoidMethod(env, cls, mid, args);
 106 
 107 }
 108 
 109 JNIEnv* atchJVM() {
 110     JNIEnv *env = NULL;
 111     int res;
 112     res = (*jvm)->AttachCurrentThread(jvm, (void**) &env, NULL);
 113     if (res < 0) {
 114         fprintf(stderr, "Thread attach failed\n");
 115         return NULL;
 116     }
 117     return env;
 118 }
 119 
 120 void* somethr(void* x) {
 121     JNIEnv *env;
 122 
 123     fprintf(stderr, "Some thread will create JVM.\n");
 124     loadJVM();
 125     env = initJVM();
 126 
 127     fprintf(stderr, "Some thread will call Java.\n");
 128 
 129     doStuff(env);
 130 
 131     if ((*jvm)->DetachCurrentThread(jvm) != 0)
 132         fputs("Error: thread not detached!\n", stderr);
 133     fprintf(stderr, "Some thread exiting.\n");
 134     return env;
 135 }
 136 
 137 int main(int argc, char **argv) {
 138     JNIEnv *env;
 139     sigset_t set;
 140     pthread_t thr1;
 141     pthread_attr_t attr;
 142     size_t ss = 0;
 143     int sig;
 144 
 145     if (argc != 2) {
 146         printf("usage: a.out jdk_path\n");
 147         exit(0);
 148     }
 149     strncpy(path, argv[1], PATH_MAX);
 150 
 151     fprintf(stderr, "Main thread will set signal mask.\n");
 152 
 153     sigemptyset(&set);
 154     sigaddset(&set, SIGPIPE);
 155     sigaddset(&set, SIGTERM);
 156     sigaddset(&set, SIGHUP);
 157     sigaddset(&set, SIGINT);
 158     pthread_sigmask(SIG_BLOCK, &set, NULL);
 159 
 160     pthread_attr_init(&attr);
 161     ss = 1024 * 1024;
 162     pthread_attr_setstacksize(&attr, ss);
 163     pthread_attr_getstacksize(&attr, &ss);
 164     fprintf(stderr, "Stack size: %zu\n", ss);
 165 
 166     pthread_create(&thr1, NULL, somethr, NULL);
 167 
 168     sigemptyset(&set);
 169     sigaddset(&set, SIGTERM);
 170     sigaddset(&set, SIGHUP);
 171     sigaddset(&set, SIGINT);
 172 
 173     fprintf(stderr, "Main thread waiting for signal.\n");
 174 
 175     do {
 176         int err;
 177 
 178         sig = 0;
 179         err = sigwait(&set, &sig);
 180         if (err != 0 && err != EINTR) {
 181             fprintf(stderr, "main: sigwait() error:  %s\n", strerror(err));
 182         } else {
 183             fprintf(stderr, "main: sigwait() got:  %d\nSucceed!\n", sig);
 184             exit(0);
 185         }
 186     } while (sig != SIGTERM && sig != SIGINT);
 187 
 188     pthread_join(thr1, NULL);
 189 
 190     dlclose(handle);
 191     fputs("Main thread exiting.\n", stderr);
 192     return 0;
 193 }
 194 #else
 195 int main(int argc, char **argv) {
 196     return 0;
 197 }
 198 #endif