2013-07-07 38 views
0

我有一個Java web應用程序,它使用tomcat 7並調用一個JNI DLL來使用Openssl EVP解密一些數據。Tomcat在Windows 7中調用JNI dll時崩潰

當在Windows XP上運行時,一切正常,但當我嘗試在Windows 7中運行它時,它會崩潰。

tomcat的stdout.log:

2013-07-07 14:23:33 Commons Daemon procrun stdout initialized 
# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x77b42b79, pid=3576, tid=1528 
# 
# JRE version: 6.0_18-b07 
# Java VM: Java HotSpot(TM) Client VM (16.0-b13 mixed mode, sharing windows-x86) 
# Problematic frame: 
# C [ntdll.dll+0x52b79] 
# 
# An error report file with more information is saved as: 
# C:\Windows\system32\hs_err_pid3576.log 
# 
# If you would like to submit a bug report, please visit: 
# http://java.sun.com/webapps/bugreport/crash.jsp 
# 
applicationContext.xml] 
[2013-07-07 14:23:52,025] INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from ServletContext resource [/WEB-INF/conf/spring/applicationContext-dataSource.xml] 
[2013-07-07 14:23:52,119] INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from ServletContext resource [/WEB-INF/conf/spring/applicationContext-manageable.xml] 
[2013-07-07 14:23:52,228] INFO [org.springframework.beans.factory.xml.XmlBeanDefinitionReader] - Loading XML bean definitions from ServletContext resource [/WEB-INF/conf/spring/applicationContext-security.xml] 
[2013-07-07 14:23:52,930] INFO [org.springframework.security.core.SpringSecurityCoreVersion] - You are running with Spring Security Core 3.0.5.RELEASE 
[2013-07-07 14:23:52,930] INFO [org.springframework.security.config.SecurityNamespaceHandler] - Spring Security 'config' module version is 3.0.5.RELEASE 
[2013-07-07 14:23:53,148] INFO [org.springframework.security.config.http.HttpSecurityBeanDefinitionParser] - ncyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null, order = 1800, <org.springframework.security.web.access.intercept.FilterSecurityInterceptor#0>, order = 1900] 

文件C:\ WINDOWS \ SYSTEM32 \ hs_err_pid3576.log表明,從JNI DLL調用的函數是錯誤的來源:

# 
# A fatal error has been detected by the Java Runtime Environment: 
# 
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x77b42b79, pid=3576, tid=1528 
# 
# JRE version: 6.0_18-b07 
# Java VM: Java HotSpot(TM) Client VM (16.0-b13 mixed mode, sharing windows-x86) 
# Problematic frame: 
# C [ntdll.dll+0x52b79] 
# 
# If you would like to submit a bug report, please visit: 
# http://java.sun.com/webapps/bugreport/crash.jsp 
# 

--------------- T H R E A D --------------- 

Current thread (0x039ab000): JavaThread "Thread-2" daemon [_thread_in_vm, id=1528, stack(0x03bf0000,0x03c60000)] 

.... 

Stack: [0x03bf0000,0x03c60000], sp=0x03c5e74c, free space=1b903c5e268k 
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code) 
C [ntdll.dll+0x52b79] 
C [ntdll.dll+0x52e7d] 
C [ntdll.dll+0x52d68] 
C [kernel32.dll+0x4f1ac] 
C [MSVCR71.dll+0x218a] 
V [jvm.dll+0x105036] 
C [myDLL.dll+0x1910] 
j myApp.d([B)[B+0 
j myApp.dec([B)[B+2 
j org.apache.catalina.h.WebappsClassLoader.findClassInternal(Ljava/lang/String;)Ljava/lang/Class;+425 
j org.apache.catalina.loader.WebappClassLoader.findClass(Ljava/lang/String;)Ljava/lang/Class;+301 
j org.apache.catalina.h.WebappsClassLoader.loadClass(Ljava/lang/String;Z)Ljava/lang/Class;+451 
j org.apache.catalina.h.WebappsClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;+3 
j org.springframework.util.ClassUtils.forName(Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class;+177 
j org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(Ljava/lang/ClassLoader;)Ljava/lang/Class;+13 
j org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(Lorg/springframework/beans/factory/support/RootBeanDefinition;[Ljava/lang/Class;)Ljava/lang/Class;+96 
j org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(Lorg/springframework/beans/factory/support/RootBeanDefinition;Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/Class;+42 
j org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(Ljava/lang/String;Lorg/springframework/beans/factory/support/RootBeanDefinition;[Ljava/lang/Class;)Ljava/lang/Class;+23 
j org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(Ljava/lang/String;Lorg/springframework/beans/factory/support/RootBeanDefinition;)Z+13 
j org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(Ljava/lang/Class;ZZ)[Ljava/lang/String;+105 
j org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(Ljava/lang/Class;ZZ)Ljava/util/Map;+4 
j org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;)V+126 
j org.springframework.context.support.AbstractApplicationContext.refresh()V+28 
j org.springframework.web.context.ContextLoader.createWebApplicationContext(Ljavax/servlet/ServletContext;Lorg/springframework/context/ApplicationContext;)Lorg/springframework/web/context/WebApplicationContext;+245 
j org.springframework.web.context.ContextLoader.initWebApplicationContext(Ljavax/servlet/ServletContext;)Lorg/springframework/web/context/WebApplicationContext;+69 
j org.springframework.web.context.ContextLoaderListener.contextInitialized(Ljavax/servlet/ServletContextEvent;)V+28 
j org.apache.catalina.core.StandardContext.listenerStart()Z+523 
j org.apache.catalina.core.StandardContext$1.call()Ljava/lang/Boolean;+12 
j org.apache.catalina.core.StandardContext$1.call()Ljava/lang/Object;+1 
j java.util.concurrent.FutureTask$Sync.innerRun()V+30 
j java.util.concurrent.FutureTask.run()V+4 
j java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Ljava/lang/Runnable;)V+59 
j java.util.concurrent.ThreadPoolExecutor$Worker.run()V+28 
j java.lang.Thread.run()V+11 
v ~StubRoutines::call_stub 
V [jvm.dll+0xf072c] 
V [jvm.dll+0x17fd51] 
V [jvm.dll+0xf08f7] 
V [jvm.dll+0xf096d] 
V [jvm.dll+0x11a4c0] 
V [jvm.dll+0x1dd924] 
V [jvm.dll+0x17f9cc] 
C [MSVCR71.dll+0x9565] 
C [kernel32.dll+0x51174] 
C [ntdll.dll+0x5b3f5] 
C [ntdll.dll+0x5b3c8] 

.... 

--------------- S Y S T E M --------------- 

OS: Windows 7 Build 7600 

CPU:total 2 (2 cores per cpu, 1 threads per core) family 6 model 23 stepping 10, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1 

Memory: 4k page, physical 2056808k(1150444k free), swap 4113616k(2684008k free) 

vm_info: Java HotSpot(TM) Client VM (16.0-b13) for windows-x86 JRE (1.6.0_18-b07), built on Dec 17 2009 13:35:55 by "java_re" with MS VC++ 7.1 (VS2003) 

time: Sun Jul 07 14:23:53 2013 
elapsed time: 19 seconds 

JNI的DLL名稱是:MYDLL.DLL 和功能是:myApp.d()

這裏是在C程序的myApp.d()函數生成該DLL:

JNIEXPORT jbyteArray JNICALL Java_myApp_d(JNIEnv *env, jobject obj, jbyteArray b) 
    { 
     EVP_CIPHER_CTX en, de; 

     // get length of bytes 
     int srcLen=(*env)->GetArrayLength(env, b); 

     //convert jbyteArray to byte [] 
     jbyte data[srcLen]; 
     (*env)->GetByteArrayRegion(env, b, 0, srcLen, data); 
     (*env)->ReleaseByteArrayElements(env, b, data , 0); 

     unsigned int salt[] = {12345, 54321}; 
     unsigned char key_data[16]={ 'A','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'}; 

    int key_data_len = 16; 


    if (aes_init(key_data, key_data_len, (unsigned char *)&salt, &en, &de)) 
    { 
     printf("Couldn't initialize AES cipher\n"); 
     return -1; 
    } 

    unsigned char* indata=(unsigned char*)data; 
    char *plaintext; 
    int olen, len; 
    int j; 


    char tampon[16]; 

    for(j=0; j<16; j++) 
    { 
     tampon[j]=indata[j]; 
    } 

    int desLen; 

    sscanf(tampon,"%d",&desLen); 

    unsigned char indataB[srcLen-16]; 

    for(j=0; j<srcLen-16; j++) 
    { 
     indataB[j]=indata[16+j]; 
    } 

    olen = len = srcLen-16+1; 


    plaintext = (char *)aes_decrypt(&de, indataB, &len); 

    jbyteArray bArray = (*env)->NewByteArray(env, desLen); 
    jboolean isCopy = JNI_TRUE; 
    jbyte* decrypteddata = (jbyte *)(*env)->GetByteArrayElements(env, bArray, &isCopy); 
    memcpy(decrypteddata, plaintext, desLen); 
    (*env)->ReleaseByteArrayElements(env, bArray, decrypteddata, 0); 



    free(plaintext); 
    free(decrypteddata); 

    EVP_CIPHER_CTX_cleanup(&en); 
    EVP_CIPHER_CTX_cleanup(&de); 

    return bArray; 

    (*env)->DeleteLocalRef(env, bArray); 
} 

該函數使用這些絲束功能:

int aes_init(unsigned char *key_data, int key_data_len, unsigned char *salt, EVP_CIPHER_CTX *e_ctx, 
      EVP_CIPHER_CTX *d_ctx) 
{ 
    int i, nrounds = 5; 
    unsigned char key[16], iv[16]; 

    /* 
    * Gen key & IV for AES 128 CBC mode. A SHA1 digest is used to hash the supplied key material. 
    * nrounds is the number of times the we hash the material. More rounds are more secure but 
    * slower. 
    */ 
    i = EVP_BytesToKey(EVP_aes_128_cbc(), EVP_sha1(), salt, key_data, key_data_len, nrounds, key, iv); 
    if (i != 16) 
    { 
     printf("Key size is %d bits - should be 128 bits\n", i); 
     return -1; 
    } 

    EVP_CIPHER_CTX_init(e_ctx); 
    EVP_EncryptInit_ex(e_ctx, EVP_aes_128_cbc(), NULL, key, iv); 
    EVP_CIPHER_CTX_init(d_ctx); 
    EVP_DecryptInit_ex(d_ctx, EVP_aes_128_cbc(), NULL, key, iv); 

    return 0; 
} 


unsigned char *aes_decrypt(EVP_CIPHER_CTX *e, unsigned char *ciphertext, int *len) 
{ 
    /* because we have padding ON, we must allocate an extra cipher block size of memory */ 
    int p_len = *len, f_len = 0; 
    unsigned char *plaintext = malloc(p_len + AES_BLOCK_SIZE+1); 

    EVP_DecryptInit_ex(e, NULL, NULL, NULL, NULL); 
    EVP_DecryptUpdate(e, plaintext, &p_len, ciphertext, *len); 
    EVP_DecryptFinal_ex(e, plaintext+p_len, &f_len); 

    *len = p_len + f_len; 
    return plaintext; 
} 

我懷疑的這一部分,其允許將數據從字符複製到* jbytearray:

jbyte* decrypteddata = (jbyte *)(*env)->GetByteArrayElements(env, bArray, &isCopy); 
memcpy(decrypteddata, plaintext, desLen); 
(*env)->ReleaseByteArrayElements(env, bArray, decrypteddata, 0); 

我試圖更換GetByteArrayElements GetPrimitiveArrayCriticalReleaseByteArrayElements by ReleasePrimitiveArrayCritical沒有成功。

回答

0

[解決]

正如我在我的問題應該,這個問題是通過調用那些拖JNI功能造成的:

(*env)->GetByteArrayRegion(env, b, 0, srcLen, data); 
    (*env)->ReleaseByteArrayElements(env, b, data , 0); 

我取而代之的是:

jbyte* d = (*env)->GetByteArrayElements(env, b, &isCopyS); 

int i; 

for(i = 0; i < srcLen; i++) 
{ 
    data[i] = d[i]; 
} 

(*env)->ReleaseByteArrayElements(env, b, d, JNI_ABORT); 

現在它可以在Windows XP和Windows 7上運行。