JNI:捕获初始化时间异常

时间:2013-04-22 12:30:25

标签: java debugging exception

好的,我对这个想法一无所知。有没有人知道如何挂钩到Java的异常管道以捕获(并记录到文本文件)正在发生的所有异常?

情况是这样的:我在JAR文件(A)中有一个库,它依赖于第二个JAR文件(B)。 A没有主类,因为它只是一个类库,我正在通过JNI访问和调用它。我遇到的问题是这个。当我尝试在加载A的情况下初始化JNI时,JNI会返回一个未指定的错误。

我强烈怀疑这个错误源于Log4J的记录器单元的实例化,它发生在B中的静态代码(方法之外)中,我相信由于日志文件上的权限问题而抛出IOException 。我有问题找出发生了什么,但是,因为异常(我怀疑是问题的原因)在链接阶段被抛出(当A导入B时)因此无法被try-catch捕获块。此外,由于没有主方法,因此没有明显的地方放置try-catch块以捕获此异常。

我想要一些方法来捕获JAR中出现的所有异常并将它们转储到文本文件中。我不能(轻松)修改B(我没有反编译的JAR)。有什么想法吗?

以下是使用指定的库和选项调用JNI的C代码:

_DLL_EXPORT PyObject *initVM(PyObject *self, PyObject *args, PyObject *kwds)
{
    static char *kwnames[] = {
        "classpath", "initialheap", "maxheap", "maxstack",
        "vmargs", NULL
    };
    char *classpath = NULL;
    char *initialheap = NULL, *maxheap = NULL, *maxstack = NULL;
    char *vmargs = NULL;

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzzzz", kwnames,
                                     &classpath,
                                     &initialheap, &maxheap, &maxstack,
                                     &vmargs))
        return NULL;

    if (env->vm)
    {
        PyObject *module_cp = NULL;

        if (initialheap || maxheap || maxstack || vmargs)
        {
            PyErr_SetString(PyExc_ValueError,
                            "JVM is already running, options are ineffective");
            return NULL;
        }

        if (classpath == NULL && self != NULL)
        {
            module_cp = PyObject_GetAttrString(self, "CLASSPATH");
            if (module_cp != NULL)
                classpath = PyString_AsString(module_cp);
        }

        if (classpath && classpath[0])
            env->setClassPath(classpath);

        Py_XDECREF(module_cp);

        return getVMEnv(self);
    }
    else
    {
        JavaVMInitArgs vm_args;
        JavaVMOption vm_options[32];
        JNIEnv *vm_env;
        JavaVM *vm;
        unsigned int nOptions = 0;
        PyObject *module_cp = NULL;

        vm_args.version = JNI_VERSION_1_4;
        JNI_GetDefaultJavaVMInitArgs(&vm_args);

        if (classpath == NULL && self != NULL)
        {
            module_cp = PyObject_GetAttrString(self, "CLASSPATH");
            if (module_cp != NULL)
                classpath = PyString_AsString(module_cp);
        }

#ifdef _jcc_lib
        PyObject *jcc = PyImport_ImportModule("jcc");
        PyObject *cp = PyObject_GetAttrString(jcc, "CLASSPATH");

        if (classpath)
            add_paths("-Djava.class.path=", PyString_AsString(cp), classpath,
                      &vm_options[nOptions++]);
        else
            add_option("-Djava.class.path=", PyString_AsString(cp),
                       &vm_options[nOptions++]);

        Py_DECREF(cp);
        Py_DECREF(jcc);
#else
        if (classpath)
            add_option("-Djava.class.path=", classpath,
                       &vm_options[nOptions++]);
#endif

        Py_XDECREF(module_cp);

        if (initialheap)
            add_option("-Xms", initialheap, &vm_options[nOptions++]);
        if (maxheap)
            add_option("-Xmx", maxheap, &vm_options[nOptions++]);
        if (maxstack)
            add_option("-Xss", maxstack, &vm_options[nOptions++]);

        if (vmargs)
        {
#ifdef _MSC_VER
            char *buf = _strdup(vmargs);
#else
            char *buf = strdup(vmargs);
#endif
            char *sep = ",";
            char *option;

            for (option = strtok(buf, sep); option; option = strtok(NULL, sep))
            {
                if (nOptions < sizeof(vm_options) / sizeof(JavaVMOption))
                    add_option("", option, &vm_options[nOptions++]);
                else
                {
                    free(buf);
                    for (unsigned int i = 0; i < nOptions; i++)
                        delete vm_options[i].optionString;
                    PyErr_Format(PyExc_ValueError, "Too many options (> %d)",
                                 nOptions);
                    return NULL;
                }
            }
            free(buf);
        }

        //vm_options[nOptions++].optionString = "-verbose:gc";
        //vm_options[nOptions++].optionString = "-Xcheck:jni";

        vm_args.nOptions = nOptions;
        vm_args.ignoreUnrecognized = JNI_FALSE;
        vm_args.options = vm_options;
 if (JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args) < 0)
        {
            for (unsigned int i = 0; i < nOptions; i++)
                delete vm_options[i].optionString;

            PyErr_Format(PyExc_ValueError,
                         "An error occurred while creating Java VM");
            return NULL;
        }

        env->set_vm(vm, vm_env);

        for (unsigned int i = 0; i < nOptions; i++)
            delete vm_options[i].optionString;

        t_jccenv *jccenv = (t_jccenv *) PY_TYPE(JCCEnv).tp_alloc(&PY_TYPE(JCCEnv), 0);
        jccenv->env = env;

#ifdef _jcc_lib
        registerNatives(vm_env);
#endif

        return (PyObject *) jccenv;
    }
}

1 个答案:

答案 0 :(得分:0)

好的,所以我得到了我追求的解决方案。该解决方案是对问题中列出的以下代码段的更新:

    if (JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args) < 0)
    {
        for (unsigned int i = 0; i < nOptions; i++)
            delete vm_options[i].optionString;

        PyErr_Format(PyExc_ValueError,
                     "An error occurred while creating Java VM");
        return NULL;
    }

改编支持构建更详细的错误消息,该消息添加了两条特定的信息:

  1. JNI_CreateJavaVM方法返回的错误代码(如果有);
  2. 在出现此类错误代码时发生的详细Java异常。
  3. 原始代码的上述代码段替换为以下内容:

        vmInitSuccess = JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args);
        if (vmInitSuccess < 0)
        {
            for (unsigned int i = 0; i < nOptions; i++)
                delete vm_options[i].optionString;
    
            //Set up basic error message
            sprintf(strVMInitSuccess, "%d", vmInitSuccess);
            strcpy(strVMError, "An error occurred while creating Java VM (No Exception): ");
            strcat(strVMError, strVMInitSuccess);
    
            //Get exception if there is one
            if((exc = vm_env->ExceptionOccurred()))
            {
                //Clear the exception since we have it now
                vm_env->ExceptionClear();
                //Get the getMessage() method
                if ((java_class = vm_env->FindClass ("java/lang/Throwable")))
                {
                    if ((method = vm_env->GetMethodID(java_class, "getMessage", "()Ljava/lang/String;")))
                    {
                        int size;
                        strExc = static_cast<jstring>(vm_env->CallObjectMethod(exc, method)); 
                        charExc = vm_env->GetStringUTFChars(strExc, NULL);
                        size = sizeof(strVMError) + sizeof(charExc);
                        char strVMException[size];
                        strcpy(strVMException, "An error occurred while creating Java VM (Exception): ");
                        strcat(strVMException, charExc);
                        PyErr_Format(PyExc_ValueError, strVMException);
                        return NULL;
                    }
                }
            }
            PyErr_Format(PyExc_ValueError, strVMError);
            return NULL;
        }
    

    感谢@Parsifal提供此解决方案的帮助。