From 3be01000302e6ea72635474ee2540b3543f8e651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Rou=C3=A9l?= Date: Fri, 20 Mar 2026 20:19:37 +0100 Subject: [PATCH] Fix issue #74 In Java 26, the internal method Class.forName0 had its signature changed from: ```java Class.forName0(String, boolean, ClassLoader, Class) // 4 params - caller removed ``` to: ```java Class.forName0(String, boolean, ClassLoader) // 3 params ``` The `caller` parameter was removed because the caller-sensitive logic was refactored to resolve the classloader on the Java side before calling the native method. The existing `GetClassByNameFunction$ForJava7` tried to look up the old 4-parameter signature via `MethodHandles`, which threw `NoSuchMethodException` on Java 26. 1. `GetClassByNameFunction.java:99-121` - Added a new `ForJava26` inner class that: - Looks up `forName0` with the new 3-parameter signature `(String, boolean, ClassLoader)` - Ignores the caller parameter in `apply()` since it's no longer needed 2. `Info.java:34` - Added `26` to `CRITICAL_VERSIONS` so the ObjectProvider will discover and use `ForJava26` when running on JDK 26+. --- ...] build and test, release if requested.yml | 2 +- .../java/io/github/toolfactory/jvm/Info.java | 2 +- .../catalog/GetClassByNameFunction.java | 25 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.github/workflows/[A] build and test, release if requested.yml b/.github/workflows/[A] build and test, release if requested.yml index b7ad31c4..cbff9ee9 100644 --- a/.github/workflows/[A] build and test, release if requested.yml +++ b/.github/workflows/[A] build and test, release if requested.yml @@ -89,7 +89,7 @@ jobs: architecture: [x64] distribution: [zulu] os: [ubuntu-latest, macOS-latest, windows-latest] - java: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] + java: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] exclude: - architecture: x64 java: 10 diff --git a/java/src/main/java/io/github/toolfactory/jvm/Info.java b/java/src/main/java/io/github/toolfactory/jvm/Info.java index c8eb739d..9db9ac3b 100644 --- a/java/src/main/java/io/github/toolfactory/jvm/Info.java +++ b/java/src/main/java/io/github/toolfactory/jvm/Info.java @@ -31,7 +31,7 @@ package io.github.toolfactory.jvm; public interface Info { - public final static int[] CRITICAL_VERSIONS = {7, 9, 14, 17, 20, 21, 22, 24, 25}; + public final static int[] CRITICAL_VERSIONS = {7, 9, 14, 17, 20, 21, 22, 24, 25, 26}; public boolean isCompressedOopsOffOn64BitHotspot(); diff --git a/java/src/main/java/io/github/toolfactory/jvm/function/catalog/GetClassByNameFunction.java b/java/src/main/java/io/github/toolfactory/jvm/function/catalog/GetClassByNameFunction.java index a46b94eb..8fb23359 100644 --- a/java/src/main/java/io/github/toolfactory/jvm/function/catalog/GetClassByNameFunction.java +++ b/java/src/main/java/io/github/toolfactory/jvm/function/catalog/GetClassByNameFunction.java @@ -95,4 +95,29 @@ public Class apply(String className, Boolean initialize, ClassLoader classLoa } + + public static class ForJava26 extends Abst { + + public ForJava26(Map context) throws Throwable { + super(context); + } + + @Override + protected MethodHandle retrieveClassFinder(Map context) throws Throwable { + ObjectProvider functionProvider = ObjectProvider.get(context); + MethodHandles.Lookup consulter = functionProvider.getOrBuildObject(DeepConsulterSupplyFunction.class, context).apply(Class.class); + // In Java 26 the caller parameter was removed from Class.forName0 + return consulter.findStatic( + Class.class, "forName0", + MethodType.methodType(Class.class, String.class, boolean.class, ClassLoader.class) + ); + } + + @Override + public Class apply(String className, Boolean initialize, ClassLoader classLoader, Class caller) throws Throwable { + return (Class)classFinder.invokeWithArguments(className, initialize.booleanValue(), classLoader); + } + + } + }