ADDITIONAL SYSTEM INFORMATION :
Windows 10
CYGWIN_NT-10.0-19043
openjdk version "23.0.2" 2025-01-21
OpenJDK Runtime Environment (build 23.0.2+7-58)
OpenJDK 64-Bit Server VM (build 23.0.2+7-58, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Using the wrong JNI in a single-file source-code program causes a segmentation fault in the JVM. By "Using the wrong JNI", I mean trying to load the "wrong" library, for example a library compiled with a header coming from same Java class but with a package declaration. The same Java program compiled with `javac` will correctly throw a "java.lang.UnsatisfiedLinkError". The same Java program put into a package and compiled with Eclipse works fine (with the same JNI library).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I discovered this possible bug by trying to use JNI but making a mistake regarding the location of the library.
Take the following Java program:
```
public class Main {
static {
System.loadLibrary("Main");
}
public static native int stringLength(final String s);
public static void main(final String[] args) {
final String s = "Hello, world!";
System.out.println(Main.stringLength(s));
}
}
```
Use `javac -h` to generate the header file:
```
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */
#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
```
And implement this header with this code:
```
#include <cstring>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_stringLength(JNIEnv *env, jclass jc, jstring js) {
const char* s = env->GetStringUTFChars(js, NULL);
return strlen(s);
}
```
Compile with `gcc -Wl,--add-stdcall-alias -shared -I"${JAVA_HOME}"/include -I"${JAVA_HOME}"/include/win32 -o Main.dll Main.cpp`
Then, you can do either `java Main.java`or `java Main`, you'll get the correct result: 13.
Now, let's make a "mistake" and modify the .h/.cpp file to declare the function as `net_ptidej_panama_jni_Main_stringLength`instead of`Java_Main_stringLength`and recompile it, still with the same name `Main.dll`.
- `java Main.class`will throw (correctly) `java.lang.UnsatisfiedLinkError`
- `java Main.java`will also throw (correctly) `java.lang.UnsatisfiedLinkError`
- But delete `Main.class` and `java Main.java`either throw (correctly) ` java.lang.UnsatisfiedLinkError` *or* writes `Segmentation fault` without further info. *or* freezes and must be killed.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
`java.lang.UnsatisfiedLinkError` should be consistently thrown.
ACTUAL -
Sometimes `java.lang.UnsatisfiedLinkError`, sometimes `Segmentation fault`, sometimes freeze.
---------- BEGIN SOURCE ----------
See steps to reproduce
---------- END SOURCE ----------
Windows 10
CYGWIN_NT-10.0-19043
openjdk version "23.0.2" 2025-01-21
OpenJDK Runtime Environment (build 23.0.2+7-58)
OpenJDK 64-Bit Server VM (build 23.0.2+7-58, mixed mode, sharing)
A DESCRIPTION OF THE PROBLEM :
Using the wrong JNI in a single-file source-code program causes a segmentation fault in the JVM. By "Using the wrong JNI", I mean trying to load the "wrong" library, for example a library compiled with a header coming from same Java class but with a package declaration. The same Java program compiled with `javac` will correctly throw a "java.lang.UnsatisfiedLinkError". The same Java program put into a package and compiled with Eclipse works fine (with the same JNI library).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
I discovered this possible bug by trying to use JNI but making a mistake regarding the location of the library.
Take the following Java program:
```
public class Main {
static {
System.loadLibrary("Main");
}
public static native int stringLength(final String s);
public static void main(final String[] args) {
final String s = "Hello, world!";
System.out.println(Main.stringLength(s));
}
}
```
Use `javac -h` to generate the header file:
```
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Main */
#ifndef _Included_Main
#define _Included_Main
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Main
* Method: stringLength
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_Main_stringLength
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
```
And implement this header with this code:
```
#include <cstring>
#include "Main.h"
JNIEXPORT jint JNICALL Java_Main_stringLength(JNIEnv *env, jclass jc, jstring js) {
const char* s = env->GetStringUTFChars(js, NULL);
return strlen(s);
}
```
Compile with `gcc -Wl,--add-stdcall-alias -shared -I"${JAVA_HOME}"/include -I"${JAVA_HOME}"/include/win32 -o Main.dll Main.cpp`
Then, you can do either `java Main.java`or `java Main`, you'll get the correct result: 13.
Now, let's make a "mistake" and modify the .h/.cpp file to declare the function as `net_ptidej_panama_jni_Main_stringLength`instead of`Java_Main_stringLength`and recompile it, still with the same name `Main.dll`.
- `java Main.class`will throw (correctly) `java.lang.UnsatisfiedLinkError`
- `java Main.java`will also throw (correctly) `java.lang.UnsatisfiedLinkError`
- But delete `Main.class` and `java Main.java`either throw (correctly) ` java.lang.UnsatisfiedLinkError` *or* writes `Segmentation fault` without further info. *or* freezes and must be killed.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
`java.lang.UnsatisfiedLinkError` should be consistently thrown.
ACTUAL -
Sometimes `java.lang.UnsatisfiedLinkError`, sometimes `Segmentation fault`, sometimes freeze.
---------- BEGIN SOURCE ----------
See steps to reproduce
---------- END SOURCE ----------