-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
199 additions
and
161 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 60 additions & 87 deletions
147
src/main/java/org/jboss/threads/EnhancedQueueExecutor.java
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package org.jboss.threads; | ||
|
||
import java.lang.reflect.Field; | ||
import java.security.AccessController; | ||
import java.security.PrivilegedAction; | ||
|
||
import sun.misc.Unsafe; | ||
|
||
final class JDKSpecific { | ||
private JDKSpecific() {} | ||
|
||
private static final Unsafe unsafe; | ||
private static final long contextClassLoaderOffs; | ||
|
||
static { | ||
unsafe = AccessController.doPrivileged(new PrivilegedAction<Unsafe>() { | ||
public Unsafe run() { | ||
try { | ||
Field field = Unsafe.class.getDeclaredField("theUnsafe"); | ||
field.setAccessible(true); | ||
return (Unsafe) field.get(null); | ||
} catch (IllegalAccessException e) { | ||
IllegalAccessError error = new IllegalAccessError(e.getMessage()); | ||
error.setStackTrace(e.getStackTrace()); | ||
throw error; | ||
} catch (NoSuchFieldException e) { | ||
NoSuchFieldError error = new NoSuchFieldError(e.getMessage()); | ||
error.setStackTrace(e.getStackTrace()); | ||
throw error; | ||
} | ||
} | ||
}); | ||
try { | ||
contextClassLoaderOffs = unsafe.objectFieldOffset(Thread.class.getDeclaredField("contextClassLoader")); | ||
} catch (NoSuchFieldException e) { | ||
NoSuchFieldError error = new NoSuchFieldError(e.getMessage()); | ||
error.setStackTrace(e.getStackTrace()); | ||
throw error; | ||
} | ||
} | ||
|
||
static void setThreadContextClassLoader(Thread thread, ClassLoader classLoader) { | ||
unsafe.putObject(thread, contextClassLoaderOffs, classLoader); | ||
} | ||
|
||
static ClassLoader getThreadContextClassLoader(Thread thread) { | ||
return (ClassLoader) unsafe.getObject(thread, contextClassLoaderOffs); | ||
} | ||
|
||
static final class ThreadAccess { | ||
private static final long threadLocalMapOffs; | ||
private static final long inheritableThreadLocalMapOffs; | ||
|
||
static { | ||
try { | ||
threadLocalMapOffs = unsafe.objectFieldOffset(Thread.class.getDeclaredField("threadLocals")); | ||
inheritableThreadLocalMapOffs = unsafe.objectFieldOffset(Thread.class.getDeclaredField("inheritableThreadLocals")); | ||
} catch (NoSuchFieldException e) { | ||
NoSuchFieldError error = new NoSuchFieldError(e.getMessage()); | ||
error.setStackTrace(e.getStackTrace()); | ||
throw error; | ||
} | ||
} | ||
|
||
static void clearThreadLocals() { | ||
Thread thread = Thread.currentThread(); | ||
unsafe.putObject(thread, threadLocalMapOffs, null); | ||
unsafe.putObject(thread, inheritableThreadLocalMapOffs, null); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package org.jboss.threads; | ||
|
||
import java.lang.invoke.MethodHandle; | ||
import java.lang.invoke.MethodHandles; | ||
import java.lang.invoke.MethodType; | ||
import java.lang.invoke.VarHandle; | ||
import java.lang.reflect.UndeclaredThrowableException; | ||
|
||
final class JDKSpecific { | ||
private JDKSpecific() {} | ||
|
||
static void setThreadContextClassLoader(Thread thread, ClassLoader classLoader) { | ||
thread.setContextClassLoader(classLoader); | ||
} | ||
|
||
static ClassLoader getThreadContextClassLoader(Thread thread) { | ||
return thread.getContextClassLoader(); | ||
} | ||
|
||
static final class ThreadAccess { | ||
private static final MethodHandle setThreadLocalsHandle; | ||
private static final MethodHandle setInheritableThreadLocalsHandle; | ||
|
||
static { | ||
try { | ||
MethodHandles.Lookup threadLookup = MethodHandles.privateLookupIn(Thread.class, MethodHandles.lookup()); | ||
setThreadLocalsHandle = threadLookup.unreflectVarHandle(Thread.class.getDeclaredField("threadLocals")).toMethodHandle(VarHandle.AccessMode.SET).asType(MethodType.methodType(void.class, Object.class)); | ||
setInheritableThreadLocalsHandle = threadLookup.unreflectVarHandle(Thread.class.getDeclaredField("inheritableThreadLocals")).toMethodHandle(VarHandle.AccessMode.SET).asType(MethodType.methodType(void.class, Object.class)); | ||
} catch (IllegalAccessException e) { | ||
Module myModule = ThreadAccess.class.getModule(); | ||
String myName = myModule.isNamed() ? myModule.getName() : "ALL-UNNAMED"; | ||
throw new IllegalAccessError(e.getMessage() + | ||
"; to use the thread-local-reset capability on Java 24 or later, use this JVM option: --add-opens java.base/java.lang=" + myName); | ||
} catch (NoSuchFieldException e) { | ||
throw new NoSuchFieldError(e.getMessage()); | ||
} | ||
} | ||
|
||
static void clearThreadLocals() { | ||
final Thread thread = Thread.currentThread(); | ||
try { | ||
setThreadLocalsHandle.invokeExact(thread, null); | ||
setInheritableThreadLocalsHandle.invokeExact(thread, null); | ||
} catch (RuntimeException | Error e) { | ||
throw e; | ||
} catch (Throwable t) { | ||
throw new UndeclaredThrowableException(t); | ||
} | ||
} | ||
} | ||
} |