📄 jk_jni_worker.c
字号:
if (0 != jni_get_default_java_vm_init_args(&vm_args)) {
jk_log(l, JK_LOG_EMERG, "can't get default vm init args");
JK_TRACE_EXIT(l);
return JK_FALSE;
}
jk_log(l, JK_LOG_DEBUG, "got default jvm args");
if (vm_args.classpath) {
unsigned len = strlen(vm_args.classpath) +
strlen(p->tomcat_classpath) + 3;
char *tmp = jk_pool_alloc(&p->p, len);
if (tmp) {
sprintf(tmp, "%s%c%s",
strdup_ascii(&p->p, p->tomcat_classpath),
PATH_SEPERATOR, vm_args.classpath);
p->tomcat_classpath = tmp;
}
else {
jk_log(l, JK_LOG_EMERG,
"allocation error for classpath");
JK_TRACE_EXIT(l);
return JK_FALSE;
}
}
vm_args.classpath = p->tomcat_classpath;
if (p->tomcat_mx) {
vm_args.maxHeapSize = p->tomcat_mx;
}
if (p->tomcat_ms) {
vm_args.minHeapSize = p->tomcat_ms;
}
if (p->sysprops) {
/* No EBCDIC to ASCII conversion here for AS/400 - later */
vm_args.properties = p->sysprops;
}
jk_log(l, JK_LOG_DEBUG, "In open_jvm1, about to create JVM...");
if ((err = jni_create_java_vm(&(p->jvm), &penv, &vm_args)) != 0) {
jk_log(l, JK_LOG_EMERG,
"could not create JVM, code: %d ", err);
JK_TRACE_EXIT(l);
return JK_FALSE;
}
jk_log(l, JK_LOG_DEBUG, "JVM created, done");
*env = penv;
JK_TRACE_EXIT(l);
return JK_TRUE;
}
#ifdef JNI_VERSION_1_2
static int detect_jvm_version(jk_logger_t *l)
{
JNIEnv *env = NULL;
JDK1_1InitArgs vm_args;
JK_TRACE_ENTER(l);
/* [V] Idea: ask for 1.2. If the JVM is 1.1 it will return 1.1 instead */
/* Note: asking for 1.1 won't work, 'cause 1.2 JVMs will return 1.1 */
vm_args.version = JNI_VERSION_1_2;
if (0 != jni_get_default_java_vm_init_args(&vm_args)) {
jk_log(l, JK_LOG_EMERG, "can't get default vm init args");
JK_TRACE_EXIT(l);
return JK_FALSE;
}
jk_log(l, JK_LOG_DEBUG,
"found version: %X, done", vm_args.version);
JK_TRACE_EXIT(l);
return vm_args.version;
}
static char *build_opt_str(jk_pool_t *p,
char *opt_name, char *opt_value, jk_logger_t *l)
{
unsigned len = strlen(opt_name) + strlen(opt_value) + 2;
/* [V] IMHO, these should not be deallocated as long as the JVM runs */
char *tmp = jk_pool_alloc(p, len);
if (tmp) {
sprintf(tmp, "%s%s", opt_name, opt_value);
return tmp;
}
else {
jk_log(l, JK_LOG_EMERG,
"allocation error for %s", opt_name);
return NULL;
}
}
static char *build_opt_int(jk_pool_t *p,
char *opt_name, int opt_value, jk_logger_t *l)
{
/* [V] this should suffice even for 64-bit int */
unsigned len = strlen(opt_name) + 20 + 2;
/* [V] IMHO, these should not be deallocated as long as the JVM runs */
char *tmp = jk_pool_alloc(p, len);
if (tmp) {
sprintf(tmp, "%s%d", opt_name, opt_value);
return tmp;
}
else {
jk_log(l, JK_LOG_EMERG,
"allocation error for %s", opt_name);
return NULL;
}
}
static int open_jvm2(jni_worker_t * p, JNIEnv ** env, jk_logger_t *l)
{
JavaVMInitArgs vm_args;
JNIEnv *penv = NULL;
JavaVMOption options[100];
int optn = 0, err;
char *tmp;
*env = NULL;
JK_TRACE_ENTER(l);
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
/* AS/400 need EBCDIC to ASCII conversion to parameters passed to JNI */
/* No conversion for ASCII based systems (what about BS2000 ?) */
if (p->tomcat_classpath) {
jk_log(l, JK_LOG_DEBUG, "setting classpath to %s",
p->tomcat_classpath);
tmp =
build_opt_str(&p->p, "-Djava.class.path=", p->tomcat_classpath,
l);
null_check(tmp);
options[optn++].optionString = strdup_ascii(&p->p, tmp);
}
if (p->tomcat_mx) {
jk_log(l, JK_LOG_DEBUG, "setting max heap to %d",
p->tomcat_mx);
tmp = build_opt_int(&p->p, "-Xmx", p->tomcat_mx, l);
null_check(tmp);
options[optn++].optionString = strdup_ascii(&p->p, tmp);
}
if (p->tomcat_ms) {
jk_log(l, JK_LOG_DEBUG, "setting start heap to %d",
p->tomcat_ms);
tmp = build_opt_int(&p->p, "-Xms", p->tomcat_ms, l);
null_check(tmp);
options[optn++].optionString = strdup_ascii(&p->p, tmp);
}
if (p->sysprops) {
int i = 0;
while (p->sysprops[i]) {
jk_log(l, JK_LOG_DEBUG, "setting %s",
p->sysprops[i]);
tmp = build_opt_str(&p->p, "-D", p->sysprops[i], l);
null_check(tmp);
options[optn++].optionString = strdup_ascii(&p->p, tmp);
i++;
}
}
if (p->java2opts) {
int i = 0;
while (p->java2opts[i]) {
jk_log(l, JK_LOG_DEBUG, "using option: %s",
p->java2opts[i]);
/* Pass it "as is" */
options[optn++].optionString =
strdup_ascii(&p->p, p->java2opts[i++]);
}
}
vm_args.nOptions = optn;
if (p->java2lax) {
jk_log(l, JK_LOG_DEBUG,
"the JVM will ignore unknown options");
vm_args.ignoreUnrecognized = JNI_TRUE;
}
else {
jk_log(l, JK_LOG_DEBUG,
"the JVM will FAIL if it finds unknown options");
vm_args.ignoreUnrecognized = JNI_FALSE;
}
jk_log(l, JK_LOG_DEBUG, "about to create JVM...");
err = jni_create_java_vm(&(p->jvm), &penv, &vm_args);
if (JNI_EEXIST == err) {
#ifdef AS400
long vmCount;
#else
int vmCount;
#endif
jk_log(l, JK_LOG_DEBUG, "JVM alread instantiated."
"Trying to attach instead.");
jni_get_created_java_vms(&(p->jvm), 1, &vmCount);
if (NULL != p->jvm)
penv = attach_to_jvm(p, l);
if (NULL != penv)
err = 0;
}
if (err != 0) {
jk_log(l, JK_LOG_EMERG, "Fail-> could not create JVM, code: %d ",
err);
JK_TRACE_EXIT(l);
return JK_FALSE;
}
*env = penv;
jk_log(l, JK_LOG_DEBUG, "JVM created");
JK_TRACE_EXIT(l);
return JK_TRUE;
}
#endif
static int get_bridge_object(jni_worker_t * p, JNIEnv * env, jk_logger_t *l)
{
char *btype;
char *ctype;
jmethodID constructor_method_id;
JK_TRACE_ENTER(l);
switch (p->bridge_type) {
case TC32_BRIDGE_TYPE:
btype = TC32_JAVA_BRIDGE_CLASS_NAME;
break;
case TC33_BRIDGE_TYPE:
btype = TC33_JAVA_BRIDGE_CLASS_NAME;
break;
case TC40_BRIDGE_TYPE:
case TC41_BRIDGE_TYPE:
case TC50_BRIDGE_TYPE:
jk_log(l, JK_LOG_EMERG, "Bridge type %d not supported",
p->bridge_type);
JK_TRACE_EXIT(l);
return JK_FALSE;
}
/* AS400/BS2000 need conversion from EBCDIC to ASCII before passing to JNI */
/* for others, strdup_ascii is just jk_pool_strdup */
ctype = strdup_ascii(&p->p, btype);
p->jk_java_bridge_class = (*env)->FindClass(env, ctype);
if (!p->jk_java_bridge_class) {
jk_log(l, JK_LOG_EMERG, "Can't find class %s", btype);
JK_TRACE_EXIT(l);
return JK_FALSE;
}
jk_log(l, JK_LOG_DEBUG,
"In get_bridge_object, loaded %s bridge class", btype);
constructor_method_id = (*env)->GetMethodID(env, p->jk_java_bridge_class, strdup_ascii(&p->p, "<init>"), /* method name */
strdup_ascii(&p->p, "()V")); /* method sign */
if (!constructor_method_id) {
p->jk_java_bridge_class = (jclass) NULL;
jk_log(l, JK_LOG_EMERG, "Can't find constructor");
JK_TRACE_EXIT(l);
return JK_FALSE;
}
p->jk_java_bridge_object = (*env)->NewObject(env,
p->jk_java_bridge_class,
constructor_method_id);
if (!p->jk_java_bridge_object) {
p->jk_java_bridge_class = (jclass) NULL;
jk_log(l, JK_LOG_EMERG, "Can't create new bridge object");
JK_TRACE_EXIT(l);
return JK_FALSE;
}
p->jk_java_bridge_object =
(jobject) (*env)->NewGlobalRef(env, p->jk_java_bridge_object);
if (!p->jk_java_bridge_object) {
jk_log(l, JK_LOG_EMERG, "Can't create global ref to bridge object");
p->jk_java_bridge_class = (jclass) NULL;
p->jk_java_bridge_object = (jobject) NULL;
JK_TRACE_EXIT(l);
return JK_FALSE;
}
JK_TRACE_EXIT(l);
return JK_TRUE;
}
static int get_method_ids(jni_worker_t * p, JNIEnv * env, jk_logger_t *l)
{
/* AS400/BS2000 need conversion from EBCDIC to ASCII before passing to JNI */
p->jk_startup_method = (*env)->GetMethodID(env,
p->jk_java_bridge_class,
strdup_ascii(&p->p, "startup"),
strdup_ascii(&p->p,
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I"));
if (!p->jk_startup_method) {
jk_log(l, JK_LOG_EMERG, "Can't find startup()");
return JK_FALSE;
}
p->jk_service_method = (*env)->GetMethodID(env,
p->jk_java_bridge_class,
strdup_ascii(&p->p, "service"),
strdup_ascii(&p->p, "(JJ)I"));
if (!p->jk_service_method) {
jk_log(l, JK_LOG_EMERG, "Can't find service()");
return JK_FALSE;
}
p->jk_shutdown_method = (*env)->GetMethodID(env,
p->jk_java_bridge_class,
strdup_ascii(&p->p,
"shutdown"),
strdup_ascii(&p->p, "()V"));
if (!p->jk_shutdown_method) {
jk_log(l, JK_LOG_EMERG, "Can't find shutdown()");
return JK_FALSE;
}
return JK_TRUE;
}
static JNIEnv *attach_to_jvm(jni_worker_t * p, jk_logger_t *l)
{
JNIEnv *rc = NULL;
/* [V] This message is important. If there are signal mask issues, *
* the JVM usually hangs when a new thread tries to attach to it */
JK_TRACE_ENTER(l);
#if defined LINUX && defined APACHE2_SIGHACK
linux_signal_hack();
#endif
if (0 == (*(p->jvm))->AttachCurrentThread(p->jvm,
#ifdef JNI_VERSION_1_2
(void **)
#endif
&rc, NULL)) {
jk_log(l, JK_LOG_DEBUG, "In attach_to_jvm, attached ok");
JK_TRACE_EXIT(l);
return rc;
}
jk_log(l, JK_LOG_ERROR,
"In attach_to_jvm, cannot attach thread to JVM.");
JK_TRACE_EXIT(l);
return NULL;
}
/*
static JNIEnv *attach_to_jvm(jni_worker_t *p)
{
JNIEnv *rc = NULL;
#ifdef LINUX
linux_signal_hack();
#endif
if(0 == (*(p->jvm))->AttachCurrentThread(p->jvm,
#ifdef JNI_VERSION_1_2
(void **)
#endif
&rc,
NULL)) {
return rc;
}
return NULL;
}
*/
static void detach_from_jvm(jni_worker_t * p, jk_logger_t *l)
{
JK_TRACE_ENTER(l);
if (!p->jvm || !(*(p->jvm))) {
jk_log(l, JK_LOG_ERROR,
"cannot detach from NULL JVM.");
}
if (0 == (*(p->jvm))->DetachCurrentThread(p->jvm)) {
jk_log(l, JK_LOG_DEBUG, "detached ok");
}
else {
jk_log(l, JK_LOG_ERROR,
"cannot detach from JVM.");
}
JK_TRACE_EXIT(l);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -