⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jk_jni_worker.c

📁 精通tomcat书籍原代码,希望大家共同学习
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 *  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: 300224 $                                           *
 ***************************************************************************/

#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_FALSE

jint(JNICALL * jni_get_default_java_vm_init_args) (void *) = NULL;
jint(JNICALL * jni_create_java_vm) (JavaVM **, JNIEnv **, void *) = NULL;
#ifdef AS400
jint(JNICALL * jni_get_created_java_vms) (JavaVM **, long, long *) = NULL;
#else
jint(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_2
static int detect_jvm_version(jk_logger_t *l);

static int open_jvm2(jni_worker_t * p, JNIEnv ** env, jk_logger_t *l);
#endif


static 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_SIGHACK
static 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");
}
#endif

static 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 + -