My goal is create text-based applications with JVM languages,
and now I am trying to use ncurses with JNI.
When I use ncurses directly from C, resizing the terminal will trigger getch()
and return 410 (KEY_RESIZE).
But I use ncurses via JNI, getch()
won t do anything until pressing any other keys.
- Is it a limitation of JVM?
- Any workaround for this situation?
- or shouldn t I use ncurses via JNI in the first place?
Here is the full reproducible code:
public class Main {
public static native void init();
public static native int getch();
public static native void printw(String string);
public static native void endwin();
public static void main(String[] args) {
System.loadLibrary("jcurses");
init();
for (int key; (key = getch()) != q ;)
printw("%d
".formatted(key));
endwin();
}
}
#include <ncurses.h>
#include "Main.h"
JNIEXPORT void JNICALL Java_Main_init(JNIEnv *env, jclass clazz) {
initscr();
keypad(stdscr, TRUE);
noecho();
}
JNIEXPORT jint JNICALL Java_Main_getch(JNIEnv *env, jclass clazz) {
return (long) getch();
}
JNIEXPORT void JNICALL Java_Main_printw(JNIEnv *env, jclass clazz, jstring javaString) {
const char *nativeString = (*env)->GetStringUTFChars(env, javaString, 0);
printw("%s", nativeString);
(*env)->ReleaseStringUTFChars(env, javaString, nativeString);
}
JNIEXPORT void JNICALL Java_Main_endwin(JNIEnv *env, jclass clazz) {
endwin();
}
all:
javac -h . Main.java
gcc -I"$$JAVA_HOME/include" -I"$$JAVA_HOME/include/linux" jcurses.c -shared -o libjcurses.so -lncurses
run:
java -Djava.library.path=. Main
For comparison, here is the pure C code to do the same thing.
Resizing the window will shows up 410 immediately but cannot do the same with JNI.
#include <ncurses.h>
int main() {
initscr();
keypad(stdscr, TRUE);
noecho();
for (int key; (key = getch()) != q ;)
printw("%d
", key);
endwin();
return 0;
}
在以下装置上测试:
- x86 ubuntu22.04, ssh from Windows 7 git bash
- arm64 ubuntu22.04, native gnome terminal