1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.corba.se.impl.transport; 27 28 import sun.misc.Unsafe; 29 import java.lang.reflect.Field; 30 import java.security.AccessController; 31 import java.security.PrivilegedAction; 32 33 /** 34 * A thread that has it's thread locals, and inheritable thread 35 * locals erased on construction. 36 */ 37 public class ManagedLocalsThread extends Thread { 38 private static final Unsafe UNSAFE; 39 private static final long THREAD_LOCALS; 40 private static final long INHERITABLE_THREAD_LOCALS; 41 42 public ManagedLocalsThread () { 43 super(); 44 } 45 46 public ManagedLocalsThread(String name) { 47 super(name); 48 eraseThreadLocals(); 49 } 50 public ManagedLocalsThread(Runnable target) { 51 super(target); 52 eraseThreadLocals(); 53 } 54 55 public ManagedLocalsThread(Runnable target, String name) { 56 super(target, name); 57 eraseThreadLocals(); 58 } 59 60 public ManagedLocalsThread(ThreadGroup group, Runnable target, String name) { 61 super(group, target, name); 62 eraseThreadLocals(); 63 } 64 65 public ManagedLocalsThread(ThreadGroup group, String name) { 66 super(group, name); 67 eraseThreadLocals(); 68 } 69 70 /** 71 * Drops all thread locals (and inherited thread locals). 72 */ 73 public final void eraseThreadLocals() { 74 UNSAFE.putObject(this, THREAD_LOCALS, null); 75 UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null); 76 } 77 78 private static Unsafe getUnsafe() { 79 PrivilegedAction<Unsafe> pa = () -> { 80 Class<?> unsafeClass = sun.misc.Unsafe.class; 81 try { 82 Field f = unsafeClass.getDeclaredField("theUnsafe"); 83 f.setAccessible(true); 84 return (Unsafe) f.get(null); 85 } catch (Exception e) { 86 throw new Error(e); 87 } 88 }; 89 return AccessController.doPrivileged(pa); 90 } 91 92 private static long getThreadFieldOffset(String fieldName) { 93 PrivilegedAction<Long> pa = () -> { 94 Class<?> t = Thread.class; 95 long fieldOffset; 96 try { 97 fieldOffset = UNSAFE.objectFieldOffset(t 98 .getDeclaredField("inheritableThreadLocals")); 99 } catch (Exception e) { 100 throw new Error(e); 101 } 102 return fieldOffset; 103 }; 104 return AccessController.doPrivileged(pa); 105 } 106 107 static { 108 UNSAFE = getUnsafe(); 109 try { 110 THREAD_LOCALS = getThreadFieldOffset("threadLocals"); 111 INHERITABLE_THREAD_LOCALS = getThreadFieldOffset("inheritableThreadLocals"); 112 } catch (Exception e) { 113 throw new Error(e); 114 } 115 } 116 }