f native image, just build a jar
This commit is contained in:
@@ -16,19 +16,16 @@ import java.util.Map;
|
||||
/**
|
||||
* A Linux PTY backed by libc via the Foreign Function & Memory API.
|
||||
*
|
||||
* <p>This replaces pty4j (which loads a JNA JNI shim that does not initialise under a
|
||||
* GraalVM native image). It uses {@code posix_openpt}/{@code posix_spawnp} rather than
|
||||
* {@code fork}/{@code forkpty}: doing work between {@code fork} and {@code exec} inside a
|
||||
* multithreaded JVM is unsafe (only async-signal-safe calls are permitted), whereas
|
||||
* {@code posix_spawn} performs the dangerous part in libc with no Java on the stack.
|
||||
* <p>This replaces pty4j (which loads a JNA JNI shim). It uses
|
||||
* {@code posix_openpt}/{@code posix_spawnp} rather than {@code fork}/{@code forkpty}:
|
||||
* doing work between {@code fork} and {@code exec} inside a multithreaded JVM is unsafe
|
||||
* (only async-signal-safe calls are permitted), whereas {@code posix_spawn} performs the
|
||||
* dangerous part in libc with no Java on the stack.
|
||||
*
|
||||
* <p>The child gets a fresh session via {@code POSIX_SPAWN_SETSID}; it then opens the slave
|
||||
* PTY itself (as fd 0, without {@code O_NOCTTY}) so the slave becomes its controlling
|
||||
* terminal. glibc applies attribute flags (the setsid) before file actions, so the open
|
||||
* happens in the new session.
|
||||
*
|
||||
* <p>FFM downcall descriptors are registered for native image by
|
||||
* {@link PtyForeignRegistrationFeature}; keep the two in sync.
|
||||
*/
|
||||
public final class LinuxPty implements AutoCloseable {
|
||||
static final Linker LINKER = Linker.nativeLinker();
|
||||
@@ -40,7 +37,7 @@ public final class LinuxPty implements AutoCloseable {
|
||||
static final ValueLayout.OfLong C_LONG = (ValueLayout.OfLong) LINKER.canonicalLayouts().get("long");
|
||||
static final ValueLayout.OfLong C_SIZE_T = (ValueLayout.OfLong) LINKER.canonicalLayouts().get("size_t");
|
||||
|
||||
// Function descriptors. Mirrored in PtyForeignRegistrationFeature.
|
||||
// Function descriptors.
|
||||
static final FunctionDescriptor FD_INT_INT = FunctionDescriptor.of(C_INT, C_INT);
|
||||
static final FunctionDescriptor FD_PTSNAME_R = FunctionDescriptor.of(C_INT, C_INT, C_POINTER, C_SIZE_T);
|
||||
static final FunctionDescriptor FD_RW = FunctionDescriptor.of(C_LONG, C_INT, C_POINTER, C_SIZE_T);
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.gregor.jprototerm;
|
||||
|
||||
import org.graalvm.nativeimage.hosted.Feature;
|
||||
import org.graalvm.nativeimage.hosted.RuntimeForeignAccess;
|
||||
|
||||
import java.lang.foreign.Linker;
|
||||
|
||||
/**
|
||||
* Registers the FFM downcall descriptors used by {@link LinuxPty} for GraalVM releases that
|
||||
* do not consume {@code foreign.downcalls} from reachability-metadata.json. Mirrors
|
||||
* jlibghostty's {@code GhosttyForeignRegistrationFeature}.
|
||||
*
|
||||
* <p>Wired in via {@code --features=com.gregor.jprototerm.PtyForeignRegistrationFeature}
|
||||
* in the gluonfx compiler args.
|
||||
*/
|
||||
public final class PtyForeignRegistrationFeature implements Feature {
|
||||
@Override
|
||||
public void duringSetup(DuringSetupAccess access) {
|
||||
downcall(LinuxPty.FD_INT_INT); // posix_openpt / grantpt / unlockpt / close
|
||||
downcall(LinuxPty.FD_PTSNAME_R); // ptsname_r
|
||||
downcall(LinuxPty.FD_RW); // read / write
|
||||
downcall(LinuxPty.FD_KILL); // kill
|
||||
downcall(LinuxPty.FD_WAITPID); // waitpid
|
||||
downcall(LinuxPty.FD_SPAWN); // posix_spawnp
|
||||
downcall(LinuxPty.FD_FA_INIT); // *_init / *_destroy
|
||||
downcall(LinuxPty.FD_FA_ADDCLOSE); // posix_spawn_file_actions_addclose
|
||||
downcall(LinuxPty.FD_FA_ADDDUP2); // posix_spawn_file_actions_adddup2
|
||||
downcall(LinuxPty.FD_FA_ADDOPEN); // posix_spawn_file_actions_addopen
|
||||
downcall(LinuxPty.FD_FA_ADDCHDIR); // posix_spawn_file_actions_addchdir_np
|
||||
downcall(LinuxPty.FD_ATTR_SETFLAGS); // posix_spawnattr_setflags
|
||||
|
||||
// ioctl(int, unsigned long, ...) is variadic; register with the same linker option.
|
||||
RuntimeForeignAccess.registerForDowncall(LinuxPty.FD_IOCTL, Linker.Option.firstVariadicArg(2));
|
||||
}
|
||||
|
||||
private static void downcall(java.lang.foreign.FunctionDescriptor descriptor) {
|
||||
RuntimeForeignAccess.registerForDowncall(descriptor);
|
||||
}
|
||||
}
|
||||
@@ -121,13 +121,24 @@ public final class TerminalCanvasView {
|
||||
String cacheKey = paneCacheKey(pane, metrics);
|
||||
int imageWidth = Math.max(1, (int) Math.ceil(pane.width()));
|
||||
int imageHeight = Math.max(1, (int) Math.ceil(pane.height()));
|
||||
if (cache.image == null || cache.canvas == null || cache.imageWidth != imageWidth || cache.imageHeight != imageHeight || !cacheKey.equals(cache.key)) {
|
||||
|
||||
// Allocate the offscreen buffers only when the pane size changes. Reallocating a
|
||||
// full-pane Canvas + WritableImage on every content change churns ~20 MB per frame,
|
||||
// which the native image's serial GC turns into Full-GC frame drops.
|
||||
if (cache.canvas == null || cache.image == null || cache.imageWidth != imageWidth || cache.imageHeight != imageHeight) {
|
||||
cache.canvas = new Canvas(imageWidth, imageHeight);
|
||||
drawPaneContent(cache.canvas.getGraphicsContext2D(), pane, font, metrics, 0.0, 0.0, imageWidth, imageHeight, true);
|
||||
cache.image = new WritableImage(imageWidth, imageHeight);
|
||||
cache.canvas.snapshot(null, cache.image);
|
||||
cache.imageWidth = imageWidth;
|
||||
cache.imageHeight = imageHeight;
|
||||
cache.key = null;
|
||||
}
|
||||
|
||||
// Redraw and re-snapshot into the existing buffers only when content changed.
|
||||
if (!cacheKey.equals(cache.key)) {
|
||||
GraphicsContext cacheGc = cache.canvas.getGraphicsContext2D();
|
||||
cacheGc.clearRect(0, 0, imageWidth, imageHeight);
|
||||
drawPaneContent(cacheGc, pane, font, metrics, 0.0, 0.0, imageWidth, imageHeight, true);
|
||||
cache.canvas.snapshot(null, cache.image);
|
||||
cache.key = cacheKey;
|
||||
}
|
||||
|
||||
|
||||
0
src/main/resources/.gitkeep
Normal file
0
src/main/resources/.gitkeep
Normal file
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"resources": []
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"resources": {
|
||||
"includes": []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user