https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61675

            Bug ID: 61675
           Summary: Wrong code generation for 32-bit x86 with
                    i686-w64-mingw32
           Product: gcc
           Version: 4.6.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: oliverst at online dot de

Created attachment 33051
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33051&action=edit
The preprocessed file using GCC 4.6.2

I have a JNI DLL, that crashes when using GetFieldID() on a class object, that
was passed into a function. The library is working fine on Linux with 32-bit
and 64-bit JVMs and only crashes when using 32-bit under Windows - 64-bit is
fine.

The original DLL was cross-compiled on ubuntu 13.10 x86_64 using MinGW-w64 GCC
4.6.3, but I also compiled it natively under Windows using MinGW-w64 GCC 4.6.3
and I still got the same crash. Using ubuntu 14.04 with MinGW-w64 4.8.2 still
produces the same error. Using Visual Studio 2010 produces a working DLL, so I
reckon this is a MinGW compiler bug.

Compiling the code as C++ by using the J NI C++ interface didn't help either.

It appears there is some memory corruption going on since when I use an
unoptimized DLL the crash doesn't happen an the first call on GetFieldID(), but
on a later one (the original DLL has way more code than the stripped down
example below) or even after the function finished somewhere in the JVM garbage
collection.

The JVM I am using is Java 7u60, but I also tried it with 8u5 and got the same
results. I tested it with the 32-bit JVM on a 64-bit and 32-bit systems as I
came across an article, that said, that a 32-bit JVM might not be reliable on
64-bit Windows operating systems (sounded a bit bogus to me, but just to be
sure).

Also there are other JNI DLLs, that don't utilize GetFieldID() at all and they
are working just fine with 32-bit.

The crash data from the hs_err_pid.log

    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

The Java class:

    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));
        }
    }

The JNI wrapper class:

    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);
    }

The application:

    package jnitest;

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

            System.exit(0);
        }
    }

The auto-generated JNI DLL header:

    /* 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

The JNI DLL implementation (**updated to be able to use either C or C++
interface**):

    #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

**Update:**

The compilation command:

        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

The MinGW of ubuntu 13.10:
Using built-in specs.
COLLECT_GCC=i686-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-w64-mingw32/4.6/lto-wrapper
Target: i686-w64-mingw32
Configured with: ../../src/configure --build=x86_64-linux-gnu --prefix=/usr
--includedir='/usr/include' --mandir='/usr/share/man'
--infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var
--libexecdir='/usr/lib/gcc-mingw-w64' --disable-maintainer-mode
--disable-dependency-tracking --prefix=/usr --enable-shared --enable-static
--disable-multilib --enable-linker-build-id --with-system-zlib
--libexecdir=/usr/lib --without-included-gettext --libdir=/usr/lib
--enable-libstdcxx-time=yes --with-tune=generic
--enable-version-specific-runtime-libs --enable-threads=win32
--enable-fully-dynamic-string --enable-sjlj-exceptions
--enable-languages=c,c++,fortran,objc,obj-c++,ada --enable-lto --with-plugin-ld
--target=i686-w64-mingw32 --with-gxx-include-dir=/usr/include/c++/4.6
--with-as=/usr/bin/i686-w64-mingw32-as --with-ld=/usr/bin/i686-w64-mingw32-ld
Thread model: win32
gcc version 4.6.3 (GCC)

The MinGW of ubuntu 14.04:

The native MinGW I used:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/mingw/mingw64-w32/bin/../libexec/gcc/i686-w64-mingw32/4.6.3/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: /home/ruben/mingw-w64/src/gcc/configure
--host=i686-w64-mingw32 --build=x86_64-linux-gnu --target=i686-w64-mingw32
--with-sysroot=/home/ruben/mingw-w64/mingw32mingw32/mingw32
--prefix=/home/ruben/mingw-w64/mingw32mingw32/mingw32
--with-gmp=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-mpfr=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-mpc=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-ppl=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-cloog=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--enable-cloog-backend=isl --with-host-libstdcxx='-static -lstdc++ -lm'
--enable-shared --enable-static --enable-threads=win32 --enable-plugins
--disable-multilib --enable-languages=c,lto,c++,objc,obj-c++,fortran,java
--enable-libgomp --disable-dw2-exceptions --enable-sjlj-exceptions
--enable-fully-dynamic-string --enable-libstdcxx-time --disable-nls
--disable-werror --enable-checking=release --with-gnu-as --with-gnu-ld
--disable-win32-registry --disable-rpath --disable-werror
--with-libiconv-prefix=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
CFLAGS='-O2 -march=nocona -mtune=core2 -fomit-frame-pointer
-momit-leaf-frame-pointer -fgraphite-identity -floop-interchange -floop-block
-floop-parallelize-all' LDFLAGS= : (reconfigured)
/home/ruben/mingw-w64/src/gcc/configure --host=i686-w64-mingw32
--build=x86_64-linux-gnu --target=i686-w64-mingw32
--with-sysroot=/home/ruben/mingw-w64/mingw32mingw32/mingw32
--prefix=/home/ruben/mingw-w64/mingw32mingw32/mingw32
--with-gmp=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-mpfr=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-mpc=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-ppl=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--with-cloog=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
--enable-cloog-backend=isl --with-host-libstdcxx='-static -lstdc++ -lm'
--enable-shared --enable-static --enable-threads=win32 --enable-plugins
--disable-multilib --enable-libgomp --disable-dw2-exceptions
--enable-sjlj-exceptions --enable-fully-dynamic-string --enable-libstdcxx-time
--disable-nls --enable-checking=release --with-gnu-as --with-gnu-ld
--disable-win32-registry --disable-rpath --disable-werror
--with-libiconv-prefix=/home/ruben/mingw-w64/prereq/i686-w64-mingw32/install
CFLAGS='-O2 -march=nocona -mtune=core2 -fomit-frame-pointer
-momit-leaf-frame-pointer -fgraphite-identity -floop-interchange -floop-block
-floop-parallelize-all' LDFLAGS= build_alias=x86_64-linux-gnu
host_alias=i686-w64-mingw32 target_alias=i686-w64-mingw32
--enable-languages=c,c++,fortran,java,lto,objc,obj-c++ --no-create
--no-recursion
Thread model: win32
gcc version 4.6.3 (GCC) 


I posted this on Stack Overflow first:
http://stackoverflow.com/questions/24485588/jni-dll-crashes-jvm-32-bit-only

Reply via email to