首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNI DLL崩溃JVM (仅32位)

JNI DLL崩溃JVM (仅32位)
EN

Stack Overflow用户
提问于 2014-06-30 08:11:23
回答 1查看 1K关注 0票数 1

我有一个JNI,当在类对象上使用GetFieldID()时会崩溃,这个DLL被传递到函数中。该库在32位和64位JVM的Linux上运行良好,只有在Windows64位下使用32位时才会崩溃。

最初的DLL是用MinGW-w64 GCC 4.6.3在but 13.10 x86_64上交叉编译的,但我也在Windows下使用MinGW-w64 GCC 4.6.3进行了本地编译,但我还是得到了相同的崩溃。在MinGW-W644.8.2中使用ubuntu14.04仍然会产生相同的错误。

似乎存在一些内存损坏,因为当我使用未优化的DLL时,崩溃不会发生在对GetFieldID()的第一次调用上,而是在稍后的调用上(原始DLL的代码比下面的简化示例多得多),甚至在函数完成JVM垃圾收集的某个地方之后也会发生崩溃。

我使用的JVM是Java7u60,但我也用8u5进行了尝试,得到了相同的结果。我在64位和32位系统上测试了32位JVM,因为我看到了一篇文章,这篇文章说,在64位Windows操作系统上,32位JVM可能不可靠(对我来说听起来有点假,但这是肯定的)。

还有其他的JNI all,它们根本不使用GetFieldID(),它们在32位的情况下工作得很好。

来自hs_err_pid.log的崩溃数据

代码语言:javascript
复制
Current thread (0x00d5e000):  JavaThread "main" [_thread_in_native, id=1104, stack(0x00dd0000,0x00e20000)]

siginfo: ExceptionCode=0xc0000005, ExceptionInformation=0x00000008 0x3462c9e8

Registers:
EAX=0x00000000, EBX=0x00e1f1fc, ECX=0x97254d7c, EDX=0x00d5eac4
ESP=0x00e1f1dc, EBP=0x00e1f1ec, ESI=0x3462c6e8, EDI=0x00d5e000
EIP=0x3462c9e8, EFLAGS=0x00010246

Top of Stack: (sp=0x00e1f1dc)
0x00e1f1dc:   00000000 3462c6e8 00000000 00e1f1fc
0x00e1f1ec:   00e1f224 025f334f 246970c0 025f88c9
0x00e1f1fc:   24695668 2460b700 00e1f204 34628d1b
0x00e1f20c:   00e1f22c 34628ee8 00000000 34628d40
0x00e1f21c:   00e1f1fc 00e1f22c 00e1f25c 025f3207
0x00e1f22c:   24693760 24693760 00000001 24693758
0x00e1f23c:   00e1f234 34628c56 00e1f264 34628ee8
0x00e1f24c:   00000000 34628c88 00e1f22c 00e1f268 

Instructions: (pc=0x3462c9e8)
0x3462c9c8:   78 bc 62 34 50 bb 62 34 c0 bd 62 34 30 bd 62 34
0x3462c9d8:   00 00 00 00 00 00 00 00 0c 00 00 00 02 00 00 00
0x3462c9e8:   01 00 00 00 60 f9 5f 39 02 00 00 00 a0 b9 62 34
0x3462c9f8:   0a 00 b8 00 10 d6 00 39 00 00 00 00 01 00 40 80 


Register to memory mapping:

EAX=0x00000000 is an unknown value
EBX=0x00e1f1fc is pointing into the stack for thread: 0x00d5e000
ECX=0x97254d7c is an unknown value
EDX=0x00d5eac4 is an unknown value
ESP=0x00e1f1dc is pointing into the stack for thread: 0x00d5e000
EBP=0x00e1f1ec is pointing into the stack for thread: 0x00d5e000
ESI=0x3462c6e8 is an oop
{method} 
 - klass: {other class}
EDI=0x00d5e000 is a thread


Stack: [0x00dd0000,0x00e20000],  sp=0x00e1f1dc,  free space=316k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  0x3462c9e8
j  jnitest.JNIClass.<init>()V+27
j  jnitest.JNIClass.getInstance()Ljnitest/JNIClass;+22
j  jnitest.Program.main([Ljava/lang/String;)V+0
v  ~StubRoutines::call_stub
V  [jvm.dll+0x140e6a]
V  [jvm.dll+0x20529e]
V  [jvm.dll+0x140eed]
V  [jvm.dll+0x14d2ee]
V  [jvm.dll+0x14d515]
V  [jvm.dll+0xf1f99]
C  [java.dll+0x7d82]
j  sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j  sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j  java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+57
j  com.intellij.rt.execution.application.AppMain.main([Ljava/lang/String;)V+163
v  ~StubRoutines::call_stub
V  [jvm.dll+0x140e6a]
V  [jvm.dll+0x20529e]
V  [jvm.dll+0x140eed]
V  [jvm.dll+0xca5c5]
V  [jvm.dll+0xd5267]
C  [java.exe+0x2063]
C  [java.exe+0xa5d1]
C  [java.exe+0xa65b]
C  [kernel32.dll+0x1338a]
C  [ntdll.dll+0x39f72]
C  [ntdll.dll+0x39f45]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  jnitest.JNIWrapper.createUuid(Ljnitest/JNIWrapper$sender_id_t;)I+25
j  jnitest.JNIClass.<init>()V+27
j  jnitest.JNIClass.getInstance()Ljnitest/JNIClass;+22
j  jnitest.Program.main([Ljava/lang/String;)V+0
v  ~StubRoutines::call_stub
j  sun.reflect.NativeMethodAccessorImpl.invoke0(Ljava/lang/reflect/Method;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+0
j  sun.reflect.NativeMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+87
j  sun.reflect.DelegatingMethodAccessorImpl.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+6
j  java.lang.reflect.Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;+57
j  com.intellij.rt.execution.application.AppMain.main([Ljava/lang/String;)V+163
v  ~StubRoutines::call_stub

Java类:

代码语言:javascript
复制
package jnitest;

public class JNIClass {
    static final Object _mutex = new Object();
    static JNIClass _instance = null;

    public static JNIClass getInstance()
    {
        if (_instance == null)
        {
            synchronized (_mutex)
            {
                if (_instance == null)
                    _instance = new JNIClass();
            }
        }
        return _instance;
    }

    JNIWrapper.sender_id_t sid = null;

    JNIClass() {
        //create uuid
        sid = new JNIWrapper.sender_id_t();
        System.out.print(JNIWrapper.createUuid(sid));
    }
}

JNI包装器类:

代码语言:javascript
复制
package jnitest;

public final class JNIWrapper {
    static {
        System.loadLibrary("JNIWrapper");
    }

    public static class sender_id_t
    {
        public long phy_idx;
    }

    public static native int createUuid(JNIWrapper.sender_id_t id);
}

申请:

代码语言:javascript
复制
package jnitest;

public class Program
{
    public static void main(String[] args)
    {
        JNIClass.getInstance();

        System.exit(0);
    }
}

自动生成的JNI DLL头:

代码语言:javascript
复制
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class jnitest_JNIWrapper */

#ifndef _Included_jnitest_JNIWrapper
#define _Included_jnitest_JNIWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jnitest_JNIWrapper
 * Method:    createUuid
 * Signature: (Ljnitest/JNIWrapper/sender_id_t;)I
 */
JNIEXPORT jint JNICALL Java_jnitest_JNIWrapper_createUuid
  (JNIEnv *, jclass, jobject);

#ifdef __cplusplus
}
#endif
#endif

JNI实现(更新后可以使用C或C++接口):

代码语言:javascript
复制
#include "jnitest_JNIWrapper.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
#define JNIFUNC(e,f)    e->f()
#define JNIFUNCV(e,f,...)   e->f(__VA_ARGS__)
#else
#define JNIFUNC(e,f)    (*e)->f(e)
#define JNIFUNCV(e,f,...)   (*e)->f(e,__VA_ARGS__)
#endif

JNIEXPORT jint JNICALL Java_jnitest_JNIWrapper_createUuid(JNIEnv *env, jclass clazz, jobject sid)
{
    (void)clazz;
    jclass cls = JNIFUNCV(env,GetObjectClass, sid);
    jfieldID phyID = JNIFUNCV(env,GetFieldID, cls, "phy_idx", "J");
    (void)phyID;
    if (JNIFUNC(env,ExceptionCheck))
        return 100;
    return 0;
}

#ifdef __cplusplus
}
#endif

更新:

编译命令:

代码语言:javascript
复制
i686-w64-mingw32-gcc -std=c99 -O3 -s -Wall -Wextra -Werror -o ../bin/JNIWrapper.dll -shared -Wl,--subsystem,windows dllmain.c JNIWrapper.c -I /usr/lib/jvm/java-7-openjdk-amd64/include
EN

回答 1

Stack Overflow用户

发布于 2014-06-30 16:26:50

您正在尝试获取内部类的字段id,但是您的cls变量是外部类JNIWrapper。您可能需要运行类似于(*env)->FindClass(env,"jnitest/JNIWrapper$sender_ id _t")的命令来获得调用get字段id的正确cls。javap -c工具可以告诉您“jnitest/JNIWrapper$发送者_id_t”应该是什么。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24485588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档