RFR: 8287496: Alternative virtual thread implementation that maps to OS thread

ExE Boss duke at openjdk.java.net
Tue May 31 11:43:15 UTC 2022


On Sun, 29 May 2022 14:46:39 GMT, Alan Bateman <alanb at openjdk.org> wrote:

> This patch adds an alternative virtual thread implementation where each virtual thread is backed by an OS thread. It doesn't scale but it can be used by ports that don't have continuations support in the VM. Aside from scalability, the lack of continuations support means:
> 
> 1. JVM TI is not supported when running with --enable-preview (the JVM TI spec allows for this) 
> 2. jshell --enable-preview can't be used (as jshell uses the debugger APIs and so needs JVM TI)
> 
> The VM option "VMContinuations" is added as an experimental option so it can be used by tests. A number of tests are changed to re-run with -XX:-VMContinuations. A new jtreg property is added so that tests that need the underlying VM support to be present can use "@requires vm.continuations" in the test description. A follow-up change would be to add "@requires vm.continuations" to the ~70 serviceability/jvmti/vthread that run with preview features enabled.

Since the package `jdk.internal.access` is exported[^1] to the `java.management` module, this can use `MethodHandle`s obtained using the trusted lookup.

[^1]: https://github.com/openjdk/jdk/blob/73ba7fdce838ba8a2c227a972c176311e6cc0b41/src/java.base/share/classes/module-info.java#L151-L154

src/java.management/share/classes/java/lang/management/ThreadInfo.java line 971:

> 969:             throw new InternalError(e);
> 970:         }
> 971:     }

Suggestion:

    private static boolean isVirtual(Thread thread) {
        try {
            return (boolean) IS_VIRTUAL.invokeExact(thread);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable t) {
            throw new InternalError(t);
        }
    }

    private static final MethodHandle IS_VIRTUAL;
    static {
        final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess();
        try {
            MethodHandle m = JLIA.findVirtual(Thread.class, "isVirtual", MethodType.methodType(boolean.class));
            assert m != null;
            IS_VIRTUAL = m;
        } catch (Exception e) {
            throw new InternalError(e);
        }
    }

src/java.management/share/classes/sun/management/ThreadImpl.java line 661:

> 659: 
> 660:     private static final Method THREAD_IS_VIRTUAL = threadIsVirtual();
> 661:     private static final Field THREADINFO_VIRTUAL = threadInfoVirtual();

Suggestion:

    private static boolean isVirtual(Thread thread) {
        try {
            return (boolean) THREAD_IS_VIRTUAL.invokeExact(thread);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable t) {
            throw new InternalError(t);
        }
    }

    /**
     * Returns true if the given ThreadInfo is for a virutal thread.
     */
    private static boolean isVirtual(ThreadInfo threadInfo) {
        try {
            return (boolean) THREADINFO_VIRTUAL.invokeExact(threadInfo);
        } catch (Error | RuntimeException e) {
            throw e;
        } catch (Throwable t) {
            throw new InternalError(t);
        }
    }

    private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess();

    private static MethodHandle threadIsVirtual() {
        try {
            MethodHandle m = JLIA.findVirtual(Thread.class, "isVirtual", MethodType.methodType(boolean.class));
            assert m != null;
            return m;
        } catch (Exception e) {
            throw new InternalError(e);
        }
    }

    @SuppressWarnings("removal")
    private static MethodHandle threadInfoVirtual() {
        PrivilegedExceptionAction<Field> pa = () -> ThreadInfo.class.getDeclaredField("virtual");
        try {
            return JLIA.unreflectField(AccessController.doPrivileged(pa), false);
        } catch (Exception e) {
            throw new InternalError(e);
        }
    }

    private static final MethodHandle THREAD_IS_VIRTUAL = threadIsVirtual();
    private static final MethodHandle THREADINFO_VIRTUAL = threadInfoVirtual();

-------------

PR: https://git.openjdk.java.net/jdk/pull/8939


More information about the serviceability-dev mailing list