8048210: More Enhancements to InnocuousThread and friends
Reviewed-by: alanb, pchelko, jbachorik
This commit is contained in:
parent
74ad666e62
commit
4b6b14f69e
@ -34,16 +34,13 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
/**
|
||||
* A thread that has no permissions, is not a member of any user-defined
|
||||
* ThreadGroup and supports the ability to erase ThreadLocals.
|
||||
*
|
||||
* @implNote Based on the implementation of InnocuousForkJoinWorkerThread.
|
||||
*/
|
||||
public final class InnocuousThread extends Thread {
|
||||
public final class InnocuousThread extends ManagedLocalsThread {
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final ThreadGroup INNOCUOUSTHREADGROUP;
|
||||
private static final AccessControlContext ACC;
|
||||
private static final long THREADLOCALS;
|
||||
private static final long INHERITABLETHREADLOCALS;
|
||||
private static final long INHERITEDACCESSCONTROLCONTEXT;
|
||||
private static final long CONTEXTCLASSLOADER;
|
||||
|
||||
private static final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
|
||||
@ -56,18 +53,10 @@ public final class InnocuousThread extends Thread {
|
||||
this(INNOCUOUSTHREADGROUP, target, name);
|
||||
}
|
||||
|
||||
private InnocuousThread(ThreadGroup group, Runnable target, String name) {
|
||||
public InnocuousThread(ThreadGroup group, Runnable target, String name) {
|
||||
super(group, target, name);
|
||||
UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
|
||||
eraseThreadLocals();
|
||||
}
|
||||
|
||||
// always report system class loader, or null
|
||||
private ClassLoader contextClassLoader = ClassLoader.getSystemClassLoader();
|
||||
|
||||
@Override
|
||||
public ClassLoader getContextClassLoader() {
|
||||
return contextClassLoader;
|
||||
UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,8 +66,9 @@ public final class InnocuousThread extends Thread {
|
||||
|
||||
@Override
|
||||
public void setContextClassLoader(ClassLoader cl) {
|
||||
// Allow clearing of the TCCL to remove the reference to the system classloader.
|
||||
if (cl == null)
|
||||
contextClassLoader = null;
|
||||
super.setContextClassLoader(null);
|
||||
else
|
||||
throw new SecurityException("setContextClassLoader");
|
||||
}
|
||||
@ -94,14 +84,6 @@ public final class InnocuousThread extends Thread {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops all thread locals (and inherited thread locals).
|
||||
*/
|
||||
public void eraseThreadLocals() {
|
||||
UNSAFE.putObject(this, THREADLOCALS, null);
|
||||
UNSAFE.putObject(this, INHERITABLETHREADLOCALS, null);
|
||||
}
|
||||
|
||||
// Use Unsafe to access Thread group and ThreadGroup parent fields
|
||||
static {
|
||||
try {
|
||||
@ -114,12 +96,10 @@ public final class InnocuousThread extends Thread {
|
||||
Class<?> tk = Thread.class;
|
||||
Class<?> gk = ThreadGroup.class;
|
||||
|
||||
THREADLOCALS = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("threadLocals"));
|
||||
INHERITABLETHREADLOCALS = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("inheritableThreadLocals"));
|
||||
INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("inheritedAccessControlContext"));
|
||||
CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
|
||||
(tk.getDeclaredField("contextClassLoader"));
|
||||
|
||||
long tg = UNSAFE.objectFieldOffset(tk.getDeclaredField("group"));
|
||||
long gp = UNSAFE.objectFieldOffset(gk.getDeclaredField("parent"));
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.misc;
|
||||
|
||||
/**
|
||||
* A thread that has it's thread locals, and inheritable thread
|
||||
* locals erased on construction.
|
||||
*/
|
||||
public class ManagedLocalsThread extends Thread {
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final long THREAD_LOCALS;
|
||||
private static final long INHERITABLE_THREAD_LOCALS;
|
||||
|
||||
public ManagedLocalsThread(Runnable target) {
|
||||
super(target);
|
||||
eraseThreadLocals();
|
||||
}
|
||||
|
||||
public ManagedLocalsThread(Runnable target, String name) {
|
||||
super(target, name);
|
||||
eraseThreadLocals();
|
||||
}
|
||||
|
||||
public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) {
|
||||
super(group, target, name);
|
||||
eraseThreadLocals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops all thread locals (and inherited thread locals).
|
||||
*/
|
||||
public final void eraseThreadLocals() {
|
||||
UNSAFE.putObject(this, THREAD_LOCALS, null);
|
||||
UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
|
||||
}
|
||||
|
||||
static {
|
||||
UNSAFE = Unsafe.getUnsafe();
|
||||
Class<?> t = Thread.class;
|
||||
try {
|
||||
THREAD_LOCALS = UNSAFE.objectFieldOffset
|
||||
(t.getDeclaredField("threadLocals"));
|
||||
INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
|
||||
(t.getDeclaredField("inheritableThreadLocals"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user