Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/misc/InnocuousThread.java
38829 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.misc;2627import java.security.AccessControlContext;28import java.security.AccessController;29import java.security.ProtectionDomain;30import java.security.PrivilegedAction;31import java.util.concurrent.atomic.AtomicInteger;3233/**34* A thread that has no permissions, is not a member of any user-defined35* ThreadGroup and supports the ability to erase ThreadLocals.36*37* @implNote Based on the implementation of InnocuousForkJoinWorkerThread.38*/39public final class InnocuousThread extends Thread {40private static final Unsafe UNSAFE;41private static final long THREAD_LOCALS;42private static final long INHERITABLE_THREAD_LOCALS;43private static final ThreadGroup INNOCUOUSTHREADGROUP;44private static final AccessControlContext ACC;45private static final long INHERITEDACCESSCONTROLCONTEXT;46private static final long CONTEXTCLASSLOADER;4748private static final AtomicInteger threadNumber = new AtomicInteger(1);49private static String newName() {50return "InnocuousThread-" + threadNumber.getAndIncrement();51}5253/**54* Returns a new InnocuousThread with an auto-generated thread name.55* Its context class loader is set to null.56*/57public static Thread newSystemThread(Runnable target) {58return newSystemThread(newName(), target);59}6061/**62* Returns a new InnocuousThread with null context class loader.63*/64public static Thread newSystemThread(String name, Runnable target) {65return new InnocuousThread(INNOCUOUSTHREADGROUP,66target, name, null);67}6869public InnocuousThread(Runnable target) {70super(INNOCUOUSTHREADGROUP, target, newName());71UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);72eraseThreadLocals();73}7475private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {76super(group, target, name, 0L);77UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);78UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, tccl);79eraseThreadLocals();80}8182@Override83public ClassLoader getContextClassLoader() {84// always report system class loader85return ClassLoader.getSystemClassLoader();86}8788@Override89public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {90// silently fail91}9293@Override94public void setContextClassLoader(ClassLoader cl) {95throw new SecurityException("setContextClassLoader");96}9798// ensure run method is run only once99private volatile boolean hasRun;100101@Override102public void run() {103if (Thread.currentThread() == this && !hasRun) {104hasRun = true;105super.run();106}107}108109/**110* Drops all thread locals (and inherited thread locals).111*/112public void eraseThreadLocals() {113UNSAFE.putObject(this, THREAD_LOCALS, null);114UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);115}116117// Use Unsafe to access Thread group and ThreadGroup parent fields118static {119try {120ACC = new AccessControlContext(new ProtectionDomain[] {121new ProtectionDomain(null, null)122});123124// Find and use topmost ThreadGroup as parent of new group125UNSAFE = Unsafe.getUnsafe();126Class<?> tk = Thread.class;127Class<?> gk = ThreadGroup.class;128129THREAD_LOCALS = UNSAFE.objectFieldOffset130(tk.getDeclaredField("threadLocals"));131INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset132(tk.getDeclaredField("inheritableThreadLocals"));133INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset134(tk.getDeclaredField("inheritedAccessControlContext"));135CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset136(tk.getDeclaredField("contextClassLoader"));137138long tg = UNSAFE.objectFieldOffset(tk.getDeclaredField("group"));139long gp = UNSAFE.objectFieldOffset(gk.getDeclaredField("parent"));140ThreadGroup group = (ThreadGroup)141UNSAFE.getObject(Thread.currentThread(), tg);142143while (group != null) {144ThreadGroup parent = (ThreadGroup)UNSAFE.getObject(group, gp);145if (parent == null)146break;147group = parent;148}149final ThreadGroup root = group;150INNOCUOUSTHREADGROUP = AccessController.doPrivileged(151new PrivilegedAction<ThreadGroup>() {152@Override153public ThreadGroup run() {154return new ThreadGroup(root, "InnocuousThreadGroup");155}156});157} catch (Exception e) {158throw new Error(e);159}160}161}162163164