java.lang.Error: Invalid memory access

1,220 views
Skip to first unread message

Piean

unread,
Jan 22, 2021, 3:38:33 AM1/22/21
to Java Native Access
I have a problem when i user JNA invoke method in dll file.
  1. JNA version:5.6.0
  2. JDK: 1.8.0_271 32bit
  3. Windows7 64bit
  4. CPU:i5-7500 3.40GHz
  5. After invoke the native method a few times, it will throw Exception:java.lang.Error: Invalid memory access
  6. Steps to reproduce
  • dll method : int BUSINESS_HANDLE(char* inputData, char* outputData)
  • java method : int BUSINESS_HANDLE(Pointer input, Pointer output);
  • method implementation:
private synchronized String sendMessage(String request) { 
  Pointer inputPointer = new Memory(request.getBytes("GBK").length + 1);        inputPointer.setString(0, request, "GBK"); 
  Pointer outputPointer = new Memory(10240); int code = libiary.BUSINESS_HANDLE(inputPointer, outputPointer); 
  String msg = outputPointer.getString(0, "GBK"); return msg; 
}  

I user same inputData, and the same outputData, but when i invoke method of "BUSINESS_HANDLE", few times, it will throw the java.lang.Error: Invalid memory access exception. like this:
The method successfully returns the first dozens of times, But sometimes a Invalid memory access exception is thrown.
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy101.BUSINESS_HANDLE(Unknown Source) 

The error occurs in the statement : String msg = outputPointer.getString(0, "GBK"); 

Can anyone help me? Thanks. 

Matthias Bläsing

unread,
Jan 22, 2021, 1:26:26 PM1/22/21
to Java Native Access
Piean schrieb am Freitag, 22. Januar 2021 um 09:38:33 UTC+1:
dll method : int BUSINESS_HANDLE(char* inputData, char* outputData)
  • java method : int BUSINESS_HANDLE(Pointer input, Pointer output);
  • method implementation:
private synchronized String sendMessage(String request) { 
  Pointer inputPointer = new Memory(request.getBytes("GBK").length + 1);        inputPointer.setString(0, request, "GBK"); 
  Pointer outputPointer = new Memory(10240); int code = libiary.BUSINESS_HANDLE(inputPointer, outputPointer); 
  String msg = outputPointer.getString(0, "GBK"); return msg; 
}  

I user same inputData, and the same outputData, but when i invoke method of "BUSINESS_HANDLE", few times, it will throw the java.lang.Error: Invalid memory access exception. like this:
The method successfully returns the first dozens of times, But sometimes a Invalid memory access exception is thrown.
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:426)
at com.sun.jna.Function.invoke(Function.java:361)
at com.sun.jna.Library$Handler.invoke(Library.java:265)
at com.sun.proxy.$Proxy101.BUSINESS_HANDLE(Unknown Source) 

The error occurs in the statement : String msg = outputPointer.getString(0, "GBK");

No it does not - at least not, if your stacktrace is to be trusted (btw. the next line in the stack trace would have been relevant ...). The stack trace ends in:

at com.sun.proxy.$Proxy101.BUSINESS_HANDLE(Unknown Source)

So that is the method, that blows up. What I notice (an what Daniel already said in the issue report): You are not zeroing out the Memory object you create (inputPointer). That means, that there is uninitialized memory. It depends on what your method does, but as no length argument is provided, it will process the inputstring by reading until a NULL byte is read.

Declare inputPointer as Memory and add an inputPointer.clear() after the object is reated, that way you get a clean slate. What I'm missing is, how it is determined how long outputData has to be. You use 10240, but that looks like speculation, if the function writes more than 10240 bytes, you'll get a segfault.

Greetings

Matthias

Piean

unread,
Jan 28, 2021, 10:52:26 PM1/28/21
to Java Native Access

I Use the same input String to invoke this method, and the output String are same to.
And the previous few invokes is successfully,  But the next time it might throw the "java.lang.Error: Invalid memory access" exception.
I add the statements after new Memory :
    inputPointer.clear(size);
    outputPointer.clear(10240);
The problem has not been solved yet. I don't know why.
And the outputData cannot exceed 10240 bytes, if more than, the exception will be thrown at the first request.
After my testing and feeling, this problem has something to do with GC.
And my appliaction will crashed after exception soon.
In the error report file, i see this information:

Register to memory mapping:
EAX=0x0000000e is an unknown value
EBX=0x27ac0001 is an unknown value
ECX=0x000002fb is an unknown value
EDX=0x00000000 is an unknown value
ESP=0x1a81eb70 is pointing into the stack for thread: 0x17bc0800
EBP=0x1a81eba4 is pointing into the stack for thread: 0x17bc0800
ESI=0x175c2de8 is an unknown value
EDI=0x27ac0000 is an unknown value

Internal exceptions (10 events):
Event: 1564.090 Thread 0x17bbec00 Exception <a 'java/lang/ClassNotFoundException': com/yunhu/pharmacy/domain/BaseDOCustomizer> (0x05642c00) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\classfile\systemDictionary.cpp, line 212]
Event: 1564.093 Thread 0x17bbec00 Exception <a 'java/lang/ClassNotFoundException': com/yunhu/pharmacy/domain/DiseaseDOCustomizer> (0x05665710) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\classfile\systemDictionary.cpp, line 212]
Event: 1624.172 Thread 0x17bba800 Exception <a 'java/net/SocketTimeoutException': Read timed out> (0x04672558) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\prims\jni.cpp, line 737]
Event: 1856.814 Thread 0x17bbc000 Exception <a 'java/lang/Error': Invalid memory access> (0x049585e8) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\prims\jni.cpp, line 737]
Event: 1872.473 Thread 0x17bbec00 Exception <a 'java/net/SocketTimeoutException': Read timed out> (0x0477b840) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\prims\jni.cpp, line 737]
Event: 1872.474 Thread 0x17bbec00 Exception <a 'java/lang/NullPointerException'> (0x0477f378) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\interpreter\linkResolver.cpp, line 1185]
Event: 1872.553 Thread 0x17bbec00 Exception <a 'java/lang/ClassNotFoundException': java/lang/ObjectCustomizer> (0x04fb2778) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\classfile\systemDictionary.cpp, line 212]
Event: 1872.554 Thread 0x17bbec00 Exception <a 'java/lang/ArrayIndexOutOfBoundsException': 22> (0x04fb5788) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\interpreter\interpreterRuntime.cpp, line 371]
Event: 1872.554 Thread 0x17bbec00 Exception <a 'java/lang/ClassNotFoundException': org/springframework/jdbc/support/SQLErrorCodesCustomizer> (0x04fd2880) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\classfile\systemDictionary.cpp, line 21
Event: 1872.555 Thread 0x17bbec00 Exception <a 'java/lang/ArrayIndexOutOfBoundsException': 80> (0x04fd7e98) thrown at [C:\jenkins\workspace\8-2-build-windows-i586-cygwin\jdk8u271\605\hotspot\src\share\vm\interpreter\interpreterRuntime.cpp, line 371]

Please help me, thanks.

Daniel Widdis

unread,
Jan 28, 2021, 11:17:08 PM1/28/21
to Java Native Access
Let me try to be explicitly clear what is happening here:' You are reporting an error in the line:

outputPointer.getString(0, "GBK");

That method starts at the pointer address you give it and reads (in the given encoding, "GBK"), until it encounters a null character, and ends.  This is not a bug; there is nothing we can do to fix or change that behavior.  In the case where it is throwing an error (Invalid Memory Access) it means that you do not control the memory that you are trying to read.   That generally is going to happen in one of two ways:
1. You free the memory and try to access it later
2. You try to access memory beyond the end of the amount you have allocated.

That is all we can really tell you from the JNA side.  From the code you have shown us, option 1 does not apply because the native memory is tied to the "Memory" object in Java that you have instantiated.  Therefore the only thing we can assume is that you are reading characters and not encountering a null character, and exceeding the 10240 bytes of allocated memory.

The problem, therefore, occurs in this method call:
BUSINESS_HANDLE(inputPointer, outputPointer); 

Something in that method is causing outputPointer's bytes to exceed the allocated 10240.  

The fact that it is an intermittent error hints to it being related to null terminated arrays.   Since you've stated you are sure the output is no more than 10240 bytes and you cleared the memory, the focus now goes to your input.  You have allocated exactly the bytes you needed plus exactly one null byte at the end:

Pointer inputPointer = new Memory(request.getBytes("GBK").length + 1);

I am not familiar with the GBK encoding but it appears to be a two byte encoding, in which case you probably need two null bytes to represent the null terminator.   Your code is succeeding when the byte immediately after your allocation is 0, and is failing when it is something else, where you are passing more to the input of the BUSINESS_HANDLE than the output can handle.

I suspect changing +1 to +2 will fix the problem, although the mismatch between allocating exactly the bytes you need on input and a fixed value on output without any length checking seems like asking for further trouble.
Reply all
Reply to author
Forward
0 new messages