Skip to content

Commit

Permalink
LDEV-5203 - fix creating virtual thread
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeloffner committed Dec 16, 2024
1 parent 0983627 commit f965144
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
56 changes: 39 additions & 17 deletions core/src/main/java/lucee/runtime/thread/ThreadUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@
import javax.servlet.http.HttpSession;

import lucee.aprint;
import lucee.print;
import lucee.commons.io.DevNullOutputStream;
import lucee.commons.io.SystemUtil;
import lucee.commons.io.log.LogUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.lang.ExceptionUtil;
import lucee.commons.lang.Pair;
Expand All @@ -54,8 +56,17 @@
public class ThreadUtil {

private static final boolean ALLOW_FUTURE_THREADS = false;
private static final Class<?> THREAD_CLASS = Thread.class;
// private static final Class<?> THREAD_CLASS = Thread.class;
private static final Class<?> RUNNABLE_CLASS = Runnable.class;
private static Class<?> threadBuilderClass;
private static boolean virtualDisabled = false;

public static Class<?> getThreadBuilderClass() throws ClassNotFoundException {
if (threadBuilderClass == null) {
threadBuilderClass = Class.forName("java.lang.Thread$Builder$OfVirtual");
}
return threadBuilderClass;
}

// do not change, used in Redis extension
public static PageContextImpl clonePageContext(PageContext pc, OutputStream os, boolean stateless, boolean register2Thread, boolean register2RunningThreads) {
Expand Down Expand Up @@ -205,42 +216,51 @@ public static Thread getThread(Runnable task) {

public static Thread getThread(Runnable task, boolean allowVirtual) {
if (allowVirtual && SystemUtil.JAVA_VERSION >= SystemUtil.JAVA_VERSION_19) {

try {
// return Thread.ofVirtual().unstarted(task);
// Get Thread.ofVirtual()
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle ofVirtualHandle = lookup.findStatic(THREAD_CLASS, "ofVirtual", MethodType.methodType(THREAD_CLASS.getDeclaredClasses()[0]));
Object builder = ofVirtualHandle.invoke();
MethodHandle unstartedHandle = lookup.findVirtual(builder.getClass(), "unstarted", MethodType.methodType(THREAD_CLASS, RUNNABLE_CLASS));
return (Thread) unstartedHandle.invoke(builder, task);
MethodHandle ofVirtualHandle = lookup.findStatic(Thread.class, "ofVirtual", MethodType.methodType(getThreadBuilderClass()));
MethodHandle unstartedHandle = lookup.findVirtual(Class.forName("java.lang.Thread$Builder"), "unstarted", MethodType.methodType(Thread.class, Runnable.class));
return (Thread) unstartedHandle.bindTo(ofVirtualHandle.invoke()).invoke(task);
}
catch (Throwable e) {
ExceptionUtil.rethrowIfNecessary(e);
LogUtil.log("threading", e);
}
}
return new Thread(task);

}

public static ExecutorService createExecutorService(int maxThreads) {
return createExecutorService(maxThreads, ALLOW_FUTURE_THREADS);
}

public static ExecutorService createExecutorService(int maxThreads, boolean allowVirtual) {
if (allowVirtual && SystemUtil.JAVA_VERSION >= SystemUtil.JAVA_VERSION_19) {
// FUTURE use newVirtualThreadPerTaskExecutor natively
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(ExecutorService.class);
MethodHandle methodHandle = lookup.findStatic(Executors.class, "newVirtualThreadPerTaskExecutor", methodType);
return (ExecutorService) methodHandle.invoke();
}
catch (Throwable e) {
ExceptionUtil.rethrowIfNecessary(e);
if (!virtualDisabled) {
if (allowVirtual && SystemUtil.JAVA_VERSION >= SystemUtil.JAVA_VERSION_19) {
// FUTURE use newVirtualThreadPerTaskExecutor natively
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(ExecutorService.class);
MethodHandle methodHandle = lookup.findStatic(Executors.class, "newVirtualThreadPerTaskExecutor", methodType);
return (ExecutorService) methodHandle.invoke();
}
catch (Throwable e) {
virtualDisabled = true;
ExceptionUtil.rethrowIfNecessary(e);
LogUtil.log("threading", e);
}
}
}
return Executors.newFixedThreadPool(maxThreads);
}

public static void main(String[] args) {
ExecutorService t = createExecutorService();
print.e(t);
}

public static ExecutorService createExecutorService() {
if (SystemUtil.JAVA_VERSION >= SystemUtil.JAVA_VERSION_19) {
// FUTURE use newVirtualThreadPerTaskExecutor natively
Expand All @@ -251,7 +271,9 @@ public static ExecutorService createExecutorService() {
return (ExecutorService) methodHandle.invoke();
}
catch (Throwable e) {
print.e(e);
ExceptionUtil.rethrowIfNecessary(e);
LogUtil.log("threading", e);
}
}
return Executors.newSingleThreadExecutor();
Expand Down
2 changes: 1 addition & 1 deletion loader/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<project default="core" basedir="." name="Lucee"
xmlns:resolver="antlib:org.apache.maven.resolver.ant">

<property name="version" value="6.2.0.217-SNAPSHOT"/>
<property name="version" value="6.2.0.218-SNAPSHOT"/>

<taskdef uri="antlib:org.apache.maven.resolver.ant" resource="org/apache/maven/resolver/ant/antlib.xml">
<classpath>
Expand Down
2 changes: 1 addition & 1 deletion loader/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.lucee</groupId>
<artifactId>lucee</artifactId>
<version>6.2.0.217-SNAPSHOT</version>
<version>6.2.0.218-SNAPSHOT</version>
<packaging>jar</packaging>

<name>Lucee Loader Build</name>
Expand Down

0 comments on commit f965144

Please sign in to comment.