Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java
41159 views
1
/*
2
* Copyright (c) 2013, 2021, 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 jdk.internal.misc;
27
28
import java.security.AccessControlContext;
29
import java.security.AccessController;
30
import java.security.ProtectionDomain;
31
import java.security.PrivilegedAction;
32
import java.util.concurrent.atomic.AtomicInteger;
33
34
/**
35
* A thread that has no permissions, is not a member of any user-defined
36
* ThreadGroup and supports the ability to erase ThreadLocals.
37
*/
38
@SuppressWarnings("removal")
39
public final class InnocuousThread extends Thread {
40
private static final jdk.internal.misc.Unsafe UNSAFE;
41
private static final long THREAD_LOCALS;
42
private static final long INHERITABLE_THREAD_LOCALS;
43
private static final ThreadGroup INNOCUOUSTHREADGROUP;
44
private static final AccessControlContext ACC;
45
private static final long INHERITEDACCESSCONTROLCONTEXT;
46
private static final long CONTEXTCLASSLOADER;
47
48
private static final AtomicInteger threadNumber = new AtomicInteger(1);
49
private static String newName() {
50
return "InnocuousThread-" + threadNumber.getAndIncrement();
51
}
52
53
/**
54
* Returns a new InnocuousThread with an auto-generated thread name,
55
* and its context class loader is set to the system class loader.
56
*/
57
public static Thread newThread(Runnable target) {
58
return newThread(newName(), target);
59
}
60
61
/**
62
* Returns a new InnocuousThread with its context class loader
63
* set to the system class loader.
64
*/
65
public static Thread newThread(String name, Runnable target) {
66
return newThread(name, target, -1);
67
}
68
/**
69
* Returns a new InnocuousThread with its context class loader
70
* set to the system class loader. The thread priority will be
71
* set to the given priority.
72
*/
73
public static Thread newThread(String name, Runnable target, int priority) {
74
if (System.getSecurityManager() == null) {
75
return createThread(name, target, ClassLoader.getSystemClassLoader(), priority);
76
}
77
return AccessController.doPrivileged(
78
new PrivilegedAction<Thread>() {
79
@Override
80
public Thread run() {
81
return createThread(name, target, ClassLoader.getSystemClassLoader(), priority);
82
}
83
});
84
}
85
86
/**
87
* Returns a new InnocuousThread with an auto-generated thread name.
88
* Its context class loader is set to null.
89
*/
90
public static Thread newSystemThread(Runnable target) {
91
return newSystemThread(newName(), target);
92
}
93
94
/**
95
* Returns a new InnocuousThread with null context class loader.
96
*/
97
public static Thread newSystemThread(String name, Runnable target) {
98
return newSystemThread(name, target, -1);
99
}
100
101
/**
102
* Returns a new InnocuousThread with null context class loader.
103
* Thread priority is set to the given priority.
104
*/
105
public static Thread newSystemThread(String name, Runnable target, int priority) {
106
if (System.getSecurityManager() == null) {
107
return createThread(name, target, null, priority);
108
}
109
return AccessController.doPrivileged(
110
new PrivilegedAction<Thread>() {
111
@Override
112
public Thread run() {
113
return createThread(name, target, null, priority);
114
}
115
});
116
}
117
118
private static Thread createThread(String name, Runnable target, ClassLoader loader, int priority) {
119
Thread t = new InnocuousThread(INNOCUOUSTHREADGROUP,
120
target, name, loader);
121
if (priority >= 0) {
122
t.setPriority(priority);
123
}
124
return t;
125
}
126
127
private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) {
128
super(group, target, name, 0L, false);
129
UNSAFE.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
130
UNSAFE.putReferenceRelease(this, CONTEXTCLASSLOADER, tccl);
131
}
132
133
@Override
134
public void setUncaughtExceptionHandler(UncaughtExceptionHandler x) {
135
// silently fail
136
}
137
138
@Override
139
public void setContextClassLoader(ClassLoader cl) {
140
// Allow clearing of the TCCL to remove the reference to the system classloader.
141
if (cl == null)
142
super.setContextClassLoader(null);
143
else
144
throw new SecurityException("setContextClassLoader");
145
}
146
147
/**
148
* Drops all thread locals (and inherited thread locals).
149
*/
150
public final void eraseThreadLocals() {
151
UNSAFE.putReference(this, THREAD_LOCALS, null);
152
UNSAFE.putReference(this, INHERITABLE_THREAD_LOCALS, null);
153
}
154
155
// ensure run method is run only once
156
private volatile boolean hasRun;
157
158
@Override
159
public void run() {
160
if (Thread.currentThread() == this && !hasRun) {
161
hasRun = true;
162
super.run();
163
}
164
}
165
166
// Use Unsafe to access Thread group and ThreadGroup parent fields
167
static {
168
try {
169
ACC = new AccessControlContext(new ProtectionDomain[] {
170
new ProtectionDomain(null, null)
171
});
172
173
// Find and use topmost ThreadGroup as parent of new group
174
UNSAFE = jdk.internal.misc.Unsafe.getUnsafe();
175
Class<?> tk = Thread.class;
176
Class<?> gk = ThreadGroup.class;
177
178
THREAD_LOCALS = UNSAFE.objectFieldOffset(tk, "threadLocals");
179
INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
180
(tk, "inheritableThreadLocals");
181
INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
182
(tk, "inheritedAccessControlContext");
183
CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
184
(tk, "contextClassLoader");
185
186
long tg = UNSAFE.objectFieldOffset(tk, "group");
187
long gp = UNSAFE.objectFieldOffset(gk, "parent");
188
ThreadGroup group = (ThreadGroup)
189
UNSAFE.getReference(Thread.currentThread(), tg);
190
191
while (group != null) {
192
ThreadGroup parent = (ThreadGroup)UNSAFE.getReference(group, gp);
193
if (parent == null)
194
break;
195
group = parent;
196
}
197
final ThreadGroup root = group;
198
if (System.getSecurityManager() == null) {
199
INNOCUOUSTHREADGROUP = new ThreadGroup(root, "InnocuousThreadGroup");
200
} else {
201
INNOCUOUSTHREADGROUP = AccessController.doPrivileged(
202
new PrivilegedAction<ThreadGroup>() {
203
@Override
204
public ThreadGroup run() {
205
return new ThreadGroup(root, "InnocuousThreadGroup");
206
}
207
});
208
}
209
} catch (Exception e) {
210
throw new Error(e);
211
}
212
}
213
}
214
215