36
36
* There is a single instance of this class, which can be obtained
37
37
* with a getInstance() call.
38
38
*
39
+ * This class also contains a couple static methods for creating
40
+ * threads. The methods allow the choice of the Runnable for the
41
+ * new thread to execute, the name of the new thread (which will
42
+ * be prefixed with "RMI "), and whether or not it will be a daemon
43
+ * thread.
44
+ *
45
+ * The new thread may be created in the system thread group (the root
46
+ * of the thread group tree) or an internally created non-system
47
+ * thread group (the "user" thread group).
48
+ *
49
+ * The new thread will have the system class loader as its initial
50
+ * context class loader (that is, its context class loader will NOT be
51
+ * inherited from the current thread).
52
+ *
39
53
* @author Peter Jones
40
54
**/
41
55
public final class RuntimeUtil {
42
56
57
+ /**
58
+ * Cached reference to the system (root) thread group.
59
+ */
60
+ private static final ThreadGroup systemThreadGroup ;
61
+ static {
62
+ ThreadGroup group = Thread .currentThread ().getThreadGroup ();
63
+ ThreadGroup parent ;
64
+ while ((parent = group .getParent ()) != null ) {
65
+ group = parent ;
66
+ }
67
+ systemThreadGroup = group ;
68
+ }
69
+
70
+ /**
71
+ * Special child of the system thread group for running tasks that
72
+ * may execute user code. The need for a separate thread group may
73
+ * be a vestige of it having had a different security policy from
74
+ * the system thread group, so this might no longer be necessary.
75
+ */
76
+ private static final ThreadGroup userThreadGroup =
77
+ new ThreadGroup (systemThreadGroup , "RMI Runtime" );
78
+
43
79
/** runtime package log */
44
80
private static final Log runtimeLog =
45
81
Log .getLog ("sun.rmi.runtime" , null , false );
@@ -54,16 +90,25 @@ public final class RuntimeUtil {
54
90
/** thread pool for scheduling delayed tasks */
55
91
private final ScheduledThreadPoolExecutor scheduler ;
56
92
93
+ /**
94
+ * Creates the single instance of RuntimeUtil. Note that this is called
95
+ * from a static initializer, and it has a ThreadFactory that calls
96
+ * static methods on this class, possibly from other threads. This
97
+ * should be ok, as the ScheduledThreadPoolExecutor constructor
98
+ * returns immediately without blocking on the creation of threads
99
+ * by the factory.
100
+ */
57
101
private RuntimeUtil () {
58
102
scheduler = new ScheduledThreadPoolExecutor (
59
103
schedulerThreads ,
60
104
new ThreadFactory () {
61
105
private final AtomicInteger count = new AtomicInteger ();
62
106
public Thread newThread (Runnable runnable ) {
63
107
try {
64
- return new NewThreadAction (runnable ,
108
+ return newSystemThread (
109
+ runnable ,
65
110
"Scheduler(" + count .getAndIncrement () + ")" ,
66
- true ). run () ;
111
+ true );
67
112
} catch (Throwable t ) {
68
113
runtimeLog .log (Level .WARNING ,
69
114
"scheduler thread factory throws" , t );
@@ -93,4 +138,48 @@ public static RuntimeUtil getInstance() {
93
138
public ScheduledThreadPoolExecutor getScheduler () {
94
139
return scheduler ;
95
140
}
141
+
142
+ // Thread creation methods.
143
+
144
+ /**
145
+ * Internal method to create a new thread with the given settings.
146
+ *
147
+ * @param group the thread group, should be systemThreadGroup or userThreadGroup
148
+ * @param runnable the thread's task
149
+ * @param name the thread's name, which will be prefixed with "RMI "
150
+ * @param daemon whether the thread should be a daemon
151
+ * @return the newly created thread
152
+ */
153
+ private static Thread newThread (ThreadGroup group , Runnable runnable , String name , boolean daemon ) {
154
+ Thread t = new Thread (group , runnable , "RMI " + name );
155
+ t .setContextClassLoader (ClassLoader .getSystemClassLoader ());
156
+ t .setDaemon (daemon );
157
+ return t ;
158
+ }
159
+
160
+ /**
161
+ * Creates and returns, but does not start, a new thread with the given settings.
162
+ * The thread will be in the system ("root") thread group.
163
+ *
164
+ * @param runnable the thread's task
165
+ * @param name the thread's name, which will be prefixed with "RMI "
166
+ * @param daemon whether the thread should be a daemon
167
+ * @return the newly created thread
168
+ */
169
+ public static Thread newSystemThread (Runnable runnable , String name , boolean daemon ) {
170
+ return newThread (systemThreadGroup , runnable , name , daemon );
171
+ }
172
+
173
+ /**
174
+ * Creates and returns, but does not start, a new thread with the given settings.
175
+ * The thread will be in the RMI user thread group.
176
+ *
177
+ * @param runnable the thread's task
178
+ * @param name the thread's name, which will be prefixed with "RMI "
179
+ * @param daemon whether the thread should be a daemon
180
+ * @return the newly created thread
181
+ */
182
+ public static Thread newUserThread (Runnable runnable , String name , boolean daemon ) {
183
+ return newThread (userThreadGroup , runnable , name , daemon );
184
+ }
96
185
}
0 commit comments