📄 jk_jni_worker.c
字号:
/* * Copyright 1999-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//*************************************************************************** * Description: In process JNI worker * * Author: Gal Shachor <shachor@il.ibm.com> * * Based on: * * Version: $Revision: 1.32 $ * ***************************************************************************/#if !defined(WIN32) && !defined(NETWARE) && !defined(AS400)#include <dlfcn.h>#endif#include <jni.h>#include "jk_pool.h"#include "jk_jni_worker.h"#include "jk_util.h"#if defined LINUX && defined APACHE2_SIGHACK#include <pthread.h>#include <signal.h>#include <bits/signum.h>#endif#ifdef NETWARE#ifdef __NOVELL_LIBC__#include <dlfcn.h>#else#include <nwthread.h>#include <nwadv.h>#endif#endif#ifndef JNI_VERSION_1_1#define JNI_VERSION_1_1 0x00010001#endif/* probably on an older system that doesn't support RTLD_NOW or RTLD_LAZY. * The below define is a lie since we are really doing RTLD_LAZY since the * system doesn't support RTLD_NOW. */#ifndef RTLD_NOW#define RTLD_NOW 1#endif#ifndef RTLD_GLOBAL#define RTLD_GLOBAL 0#endif#define null_check(e) if ((e) == 0) return JK_FALSEjint(JNICALL * jni_get_default_java_vm_init_args) (void *) = NULL;jint(JNICALL * jni_create_java_vm) (JavaVM **, JNIEnv **, void *) = NULL;#ifdef AS400jint(JNICALL * jni_get_created_java_vms) (JavaVM **, long, long *) = NULL;#elsejint(JNICALL * jni_get_created_java_vms) (JavaVM **, int, int *) = NULL;#endif#define TC33_JAVA_BRIDGE_CLASS_NAME ("org/apache/tomcat/modules/server/JNIEndpoint")#define TC32_JAVA_BRIDGE_CLASS_NAME ("org/apache/tomcat/service/JNIEndpoint")static jk_worker_t *the_singleton_jni_worker = NULL;struct jni_worker{ int was_verified; int was_initialized; jk_pool_t p; jk_pool_atom_t buf[TINY_POOL_SIZE]; /* * JVM Object pointer. */ JavaVM *jvm; /* * [V] JNIEnv used for boostraping from validate -> init w/o an attach */ JNIEnv *tmp_env; /* * Web Server to Java bridge, instance and class. */ jobject jk_java_bridge_object; jclass jk_java_bridge_class; /* * Java methods ids, to jump into the JVM */ jmethodID jk_startup_method; jmethodID jk_service_method; jmethodID jk_shutdown_method; /* * Command line for tomcat startup */ char *tomcat_cmd_line; /* * Bridge Type, Tomcat 32/33/40/41/5 */ unsigned bridge_type; /* * Classpath */ char *tomcat_classpath; /* * Full path to the jni javai/jvm dll */ char *jvm_dll_path; /* * Initial Java heap size */ unsigned tomcat_ms; /* * Max Java heap size */ unsigned tomcat_mx; /* * Java system properties */ char **sysprops;#ifdef JNI_VERSION_1_2 /* * Java 2 initialization options (-X... , -verbose etc.) */ char **java2opts; /* * Java 2 lax/strict option checking (bool) */ int java2lax;#endif /* * stdout and stderr file names for Java */ char *stdout_name; char *stderr_name; char *name; jk_worker_t worker;};typedef struct jni_worker jni_worker_t;struct jni_endpoint{ int attached; JNIEnv *env; jni_worker_t *worker; jk_endpoint_t endpoint;};typedef struct jni_endpoint jni_endpoint_t;static int load_jvm_dll(jni_worker_t * p, jk_logger_t *l);static int open_jvm(jni_worker_t * p, JNIEnv ** env, jk_logger_t *l);static int open_jvm1(jni_worker_t * p, JNIEnv ** env, jk_logger_t *l);#ifdef JNI_VERSION_1_2static int detect_jvm_version(jk_logger_t *l);static int open_jvm2(jni_worker_t * p, JNIEnv ** env, jk_logger_t *l);#endifstatic int get_bridge_object(jni_worker_t * p, JNIEnv * env, jk_logger_t *l);static int get_method_ids(jni_worker_t * p, JNIEnv * env, jk_logger_t *l);static JNIEnv *attach_to_jvm(jni_worker_t * p, jk_logger_t *l);static void detach_from_jvm(jni_worker_t * p, jk_logger_t *l);/* Duplicate string and convert it to ASCII on EBDIC based systems Needed for at least AS/400 and BS2000 but what about other EBDIC systems ?*/static void *strdup_ascii(jk_pool_t *p, char *s){ char *rc; rc = jk_pool_strdup(p, s);#if defined(AS400) || defined(_OSD_POSIX) jk_xlate_to_ascii(rc, strlen(rc));#endif return rc;}#if defined LINUX && defined APACHE2_SIGHACKstatic void linux_signal_hack(){ sigset_t newM; sigset_t old; sigemptyset(&newM); pthread_sigmask(SIG_SETMASK, &newM, &old); sigdelset(&old, SIGUSR1); sigdelset(&old, SIGUSR2); sigdelset(&old, SIGUNUSED); sigdelset(&old, SIGRTMIN); sigdelset(&old, SIGRTMIN + 1); sigdelset(&old, SIGRTMIN + 2); pthread_sigmask(SIG_SETMASK, &old, NULL);}static void print_signals(sigset_t * sset){ int sig; for (sig = 1; sig < 20; sig++) { if (sigismember(sset, sig)) { printf(" %d", sig); } } printf("\n");}#endifstatic int JK_METHOD service(jk_endpoint_t *e, jk_ws_service_t *s, jk_logger_t *l, int *is_recoverable_error){ jni_endpoint_t *p; jint rc; JK_TRACE_ENTER(l); if (!e || !e->endpoint_private || !s) { JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } p = e->endpoint_private; if (!is_recoverable_error) { JK_TRACE_EXIT(l); return JK_FALSE; } if (!p->attached) { /* Try to attach */ if (!(p->env = attach_to_jvm(p->worker, l))) { jk_log(l, JK_LOG_EMERG, "Attach failed"); /* Is it recoverable ?? */ *is_recoverable_error = JK_TRUE; JK_TRACE_EXIT(l); return JK_FALSE; } p->attached = JK_TRUE; } /* we are attached now */ /* * When we call the JVM we cannot know what happens * So we can not recover !!! */ *is_recoverable_error = JK_FALSE; jk_log(l, JK_LOG_DEBUG, "In service, calling Tomcat..."); rc = (*(p->env))->CallIntMethod(p->env, p->worker->jk_java_bridge_object, p->worker->jk_service_method, /* [V] For some reason gcc likes this pointer -> int -> jlong conversion, */ /* but not the direct pointer -> jlong conversion. I hope it's okay. */#ifdef AS400 s, l#else (jlong) (int)s, (jlong) (int)l#endif ); /* [V] Righ now JNIEndpoint::service() only returns 1 or 0 */ if (rc) { jk_log(l, JK_LOG_DEBUG, "Tomcat returned OK, done"); JK_TRACE_EXIT(l); return JK_TRUE; } else { jk_log(l, JK_LOG_ERROR, "Tomcat FAILED!"); JK_TRACE_EXIT(l); return JK_FALSE; }}static int JK_METHOD done(jk_endpoint_t **e, jk_logger_t *l){ jni_endpoint_t *p; JK_TRACE_ENTER(l); if (!e || !*e || !(*e)->endpoint_private) { JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } p = (*e)->endpoint_private; if (p->attached) { detach_from_jvm(p->worker, l); } free(p); *e = NULL; JK_TRACE_EXIT(l); return JK_TRUE;}static int JK_METHOD validate(jk_worker_t *pThis, jk_map_t *props, jk_worker_env_t *we, jk_logger_t *l){ jni_worker_t *p; int mem_config = 0; int btype = 0; const char *str_config = NULL; JNIEnv *env; JK_TRACE_ENTER(l); if (!pThis || !pThis->worker_private) { JK_LOG_NULL_PARAMS(l); JK_TRACE_EXIT(l); return JK_FALSE; } p = pThis->worker_private; if (p->was_verified) { jk_log(l, JK_LOG_DEBUG, "been here before, done"); JK_TRACE_EXIT(l); return JK_TRUE; } if (jk_get_worker_mx(props, p->name, (unsigned int *)&mem_config)) { p->tomcat_mx = mem_config; } if (jk_get_worker_ms(props, p->name, (unsigned int *)&mem_config)) { p->tomcat_ms = mem_config; } if (jk_get_worker_classpath(props, p->name, &str_config)) { p->tomcat_classpath = jk_pool_strdup(&p->p, str_config); } if (!p->tomcat_classpath) { jk_log(l, JK_LOG_EMERG, "no classpath"); JK_TRACE_EXIT(l); return JK_FALSE; } if (jk_get_worker_bridge_type(props, p->name, (unsigned int *)&btype)) { p->bridge_type = btype; } if (jk_get_worker_jvm_path(props, p->name, &str_config)) { p->jvm_dll_path = jk_pool_strdup(&p->p, str_config); } if (!p->jvm_dll_path || !jk_file_exists(p->jvm_dll_path)) { jk_log(l, JK_LOG_EMERG, "no jvm_dll_path"); JK_TRACE_EXIT(l); return JK_FALSE; } if (jk_get_worker_cmd_line(props, p->name, &str_config)) { p->tomcat_cmd_line = jk_pool_strdup(&p->p, str_config); } if (jk_get_worker_stdout(props, p->name, &str_config)) { p->stdout_name = jk_pool_strdup(&p->p, str_config); } if (jk_get_worker_stderr(props, p->name, &str_config)) { p->stderr_name = jk_pool_strdup(&p->p, str_config); } if (jk_get_worker_sysprops(props, p->name, &str_config)) { p->sysprops = jk_parse_sysprops(&p->p, str_config); }#ifdef JNI_VERSION_1_2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -