8048210: More Enhancements to InnocuousThread and friends

Reviewed-by: alanb, pchelko, jbachorik
This commit is contained in:
Chris Hegarty 2014-06-26 14:49:23 +01:00
parent 74ad666e62
commit 4b6b14f69e
2 changed files with 81 additions and 28 deletions

View File

@ -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"));

View File

@ -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);
}
}
}