Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/instrument/InstrumentationImpl.java
38829 views
1
/*
2
* Copyright (c) 2003, 2013, 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
27
package sun.instrument;
28
29
import java.lang.reflect.Method;
30
import java.lang.reflect.AccessibleObject;
31
32
import java.lang.instrument.ClassFileTransformer;
33
import java.lang.instrument.ClassDefinition;
34
import java.lang.instrument.Instrumentation;
35
36
import java.security.AccessController;
37
import java.security.PrivilegedAction;
38
import java.security.ProtectionDomain;
39
40
import java.util.jar.JarFile;
41
42
/*
43
* Copyright 2003 Wily Technology, Inc.
44
*/
45
46
/**
47
* The Java side of the JPLIS implementation. Works in concert with a native JVMTI agent
48
* to implement the JPLIS API set. Provides both the Java API implementation of
49
* the Instrumentation interface and utility Java routines to support the native code.
50
* Keeps a pointer to the native data structure in a scalar field to allow native
51
* processing behind native methods.
52
*/
53
public class InstrumentationImpl implements Instrumentation {
54
private final TransformerManager mTransformerManager;
55
private TransformerManager mRetransfomableTransformerManager;
56
// needs to store a native pointer, so use 64 bits
57
private final long mNativeAgent;
58
private final boolean mEnvironmentSupportsRedefineClasses;
59
private volatile boolean mEnvironmentSupportsRetransformClassesKnown;
60
private volatile boolean mEnvironmentSupportsRetransformClasses;
61
private final boolean mEnvironmentSupportsNativeMethodPrefix;
62
63
private
64
InstrumentationImpl(long nativeAgent,
65
boolean environmentSupportsRedefineClasses,
66
boolean environmentSupportsNativeMethodPrefix) {
67
mTransformerManager = new TransformerManager(false);
68
mRetransfomableTransformerManager = null;
69
mNativeAgent = nativeAgent;
70
mEnvironmentSupportsRedefineClasses = environmentSupportsRedefineClasses;
71
mEnvironmentSupportsRetransformClassesKnown = false; // false = need to ask
72
mEnvironmentSupportsRetransformClasses = false; // don't know yet
73
mEnvironmentSupportsNativeMethodPrefix = environmentSupportsNativeMethodPrefix;
74
}
75
76
public void
77
addTransformer(ClassFileTransformer transformer) {
78
addTransformer(transformer, false);
79
}
80
81
public synchronized void
82
addTransformer(ClassFileTransformer transformer, boolean canRetransform) {
83
if (transformer == null) {
84
throw new NullPointerException("null passed as 'transformer' in addTransformer");
85
}
86
if (canRetransform) {
87
if (!isRetransformClassesSupported()) {
88
throw new UnsupportedOperationException(
89
"adding retransformable transformers is not supported in this environment");
90
}
91
if (mRetransfomableTransformerManager == null) {
92
mRetransfomableTransformerManager = new TransformerManager(true);
93
}
94
mRetransfomableTransformerManager.addTransformer(transformer);
95
if (mRetransfomableTransformerManager.getTransformerCount() == 1) {
96
setHasRetransformableTransformers(mNativeAgent, true);
97
}
98
} else {
99
mTransformerManager.addTransformer(transformer);
100
}
101
}
102
103
public synchronized boolean
104
removeTransformer(ClassFileTransformer transformer) {
105
if (transformer == null) {
106
throw new NullPointerException("null passed as 'transformer' in removeTransformer");
107
}
108
TransformerManager mgr = findTransformerManager(transformer);
109
if (mgr != null) {
110
mgr.removeTransformer(transformer);
111
if (mgr.isRetransformable() && mgr.getTransformerCount() == 0) {
112
setHasRetransformableTransformers(mNativeAgent, false);
113
}
114
return true;
115
}
116
return false;
117
}
118
119
public boolean
120
isModifiableClass(Class<?> theClass) {
121
if (theClass == null) {
122
throw new NullPointerException(
123
"null passed as 'theClass' in isModifiableClass");
124
}
125
return isModifiableClass0(mNativeAgent, theClass);
126
}
127
128
public boolean
129
isRetransformClassesSupported() {
130
// ask lazily since there is some overhead
131
if (!mEnvironmentSupportsRetransformClassesKnown) {
132
mEnvironmentSupportsRetransformClasses = isRetransformClassesSupported0(mNativeAgent);
133
mEnvironmentSupportsRetransformClassesKnown = true;
134
}
135
return mEnvironmentSupportsRetransformClasses;
136
}
137
138
public void
139
retransformClasses(Class<?>... classes) {
140
if (!isRetransformClassesSupported()) {
141
throw new UnsupportedOperationException(
142
"retransformClasses is not supported in this environment");
143
}
144
retransformClasses0(mNativeAgent, classes);
145
}
146
147
public boolean
148
isRedefineClassesSupported() {
149
return mEnvironmentSupportsRedefineClasses;
150
}
151
152
public void
153
redefineClasses(ClassDefinition... definitions)
154
throws ClassNotFoundException {
155
if (!isRedefineClassesSupported()) {
156
throw new UnsupportedOperationException("redefineClasses is not supported in this environment");
157
}
158
if (definitions == null) {
159
throw new NullPointerException("null passed as 'definitions' in redefineClasses");
160
}
161
for (int i = 0; i < definitions.length; ++i) {
162
if (definitions[i] == null) {
163
throw new NullPointerException("element of 'definitions' is null in redefineClasses");
164
}
165
}
166
if (definitions.length == 0) {
167
return; // short-circuit if there are no changes requested
168
}
169
170
redefineClasses0(mNativeAgent, definitions);
171
}
172
173
@SuppressWarnings("rawtypes")
174
public Class[]
175
getAllLoadedClasses() {
176
return getAllLoadedClasses0(mNativeAgent);
177
}
178
179
@SuppressWarnings("rawtypes")
180
public Class[]
181
getInitiatedClasses(ClassLoader loader) {
182
return getInitiatedClasses0(mNativeAgent, loader);
183
}
184
185
public long
186
getObjectSize(Object objectToSize) {
187
if (objectToSize == null) {
188
throw new NullPointerException("null passed as 'objectToSize' in getObjectSize");
189
}
190
return getObjectSize0(mNativeAgent, objectToSize);
191
}
192
193
public void
194
appendToBootstrapClassLoaderSearch(JarFile jarfile) {
195
appendToClassLoaderSearch0(mNativeAgent, jarfile.getName(), true);
196
}
197
198
public void
199
appendToSystemClassLoaderSearch(JarFile jarfile) {
200
appendToClassLoaderSearch0(mNativeAgent, jarfile.getName(), false);
201
}
202
203
public boolean
204
isNativeMethodPrefixSupported() {
205
return mEnvironmentSupportsNativeMethodPrefix;
206
}
207
208
public synchronized void
209
setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
210
if (!isNativeMethodPrefixSupported()) {
211
throw new UnsupportedOperationException(
212
"setNativeMethodPrefix is not supported in this environment");
213
}
214
if (transformer == null) {
215
throw new NullPointerException(
216
"null passed as 'transformer' in setNativeMethodPrefix");
217
}
218
TransformerManager mgr = findTransformerManager(transformer);
219
if (mgr == null) {
220
throw new IllegalArgumentException(
221
"transformer not registered in setNativeMethodPrefix");
222
}
223
mgr.setNativeMethodPrefix(transformer, prefix);
224
String[] prefixes = mgr.getNativeMethodPrefixes();
225
setNativeMethodPrefixes(mNativeAgent, prefixes, mgr.isRetransformable());
226
}
227
228
private TransformerManager
229
findTransformerManager(ClassFileTransformer transformer) {
230
if (mTransformerManager.includesTransformer(transformer)) {
231
return mTransformerManager;
232
}
233
if (mRetransfomableTransformerManager != null &&
234
mRetransfomableTransformerManager.includesTransformer(transformer)) {
235
return mRetransfomableTransformerManager;
236
}
237
return null;
238
}
239
240
241
/*
242
* Natives
243
*/
244
private native boolean
245
isModifiableClass0(long nativeAgent, Class<?> theClass);
246
247
private native boolean
248
isRetransformClassesSupported0(long nativeAgent);
249
250
private native void
251
setHasRetransformableTransformers(long nativeAgent, boolean has);
252
253
private native void
254
retransformClasses0(long nativeAgent, Class<?>[] classes);
255
256
private native void
257
redefineClasses0(long nativeAgent, ClassDefinition[] definitions)
258
throws ClassNotFoundException;
259
260
@SuppressWarnings("rawtypes")
261
private native Class[]
262
getAllLoadedClasses0(long nativeAgent);
263
264
@SuppressWarnings("rawtypes")
265
private native Class[]
266
getInitiatedClasses0(long nativeAgent, ClassLoader loader);
267
268
private native long
269
getObjectSize0(long nativeAgent, Object objectToSize);
270
271
private native void
272
appendToClassLoaderSearch0(long nativeAgent, String jarfile, boolean bootLoader);
273
274
private native void
275
setNativeMethodPrefixes(long nativeAgent, String[] prefixes, boolean isRetransformable);
276
277
static {
278
System.loadLibrary("instrument");
279
}
280
281
/*
282
* Internals
283
*/
284
285
286
// Enable or disable Java programming language access checks on a
287
// reflected object (for example, a method)
288
private static void setAccessible(final AccessibleObject ao, final boolean accessible) {
289
AccessController.doPrivileged(new PrivilegedAction<Object>() {
290
public Object run() {
291
ao.setAccessible(accessible);
292
return null;
293
}});
294
}
295
296
// Attempt to load and start an agent
297
private void
298
loadClassAndStartAgent( String classname,
299
String methodname,
300
String optionsString)
301
throws Throwable {
302
303
ClassLoader mainAppLoader = ClassLoader.getSystemClassLoader();
304
Class<?> javaAgentClass = mainAppLoader.loadClass(classname);
305
306
Method m = null;
307
NoSuchMethodException firstExc = null;
308
boolean twoArgAgent = false;
309
310
// The agent class must have a premain or agentmain method that
311
// has 1 or 2 arguments. We check in the following order:
312
//
313
// 1) declared with a signature of (String, Instrumentation)
314
// 2) declared with a signature of (String)
315
// 3) inherited with a signature of (String, Instrumentation)
316
// 4) inherited with a signature of (String)
317
//
318
// So the declared version of either 1-arg or 2-arg always takes
319
// primary precedence over an inherited version. After that, the
320
// 2-arg version takes precedence over the 1-arg version.
321
//
322
// If no method is found then we throw the NoSuchMethodException
323
// from the first attempt so that the exception text indicates
324
// the lookup failed for the 2-arg method (same as JDK5.0).
325
326
try {
327
m = javaAgentClass.getDeclaredMethod( methodname,
328
new Class<?>[] {
329
String.class,
330
java.lang.instrument.Instrumentation.class
331
}
332
);
333
twoArgAgent = true;
334
} catch (NoSuchMethodException x) {
335
// remember the NoSuchMethodException
336
firstExc = x;
337
}
338
339
if (m == null) {
340
// now try the declared 1-arg method
341
try {
342
m = javaAgentClass.getDeclaredMethod(methodname,
343
new Class<?>[] { String.class });
344
} catch (NoSuchMethodException x) {
345
// ignore this exception because we'll try
346
// two arg inheritance next
347
}
348
}
349
350
if (m == null) {
351
// now try the inherited 2-arg method
352
try {
353
m = javaAgentClass.getMethod( methodname,
354
new Class<?>[] {
355
String.class,
356
java.lang.instrument.Instrumentation.class
357
}
358
);
359
twoArgAgent = true;
360
} catch (NoSuchMethodException x) {
361
// ignore this exception because we'll try
362
// one arg inheritance next
363
}
364
}
365
366
if (m == null) {
367
// finally try the inherited 1-arg method
368
try {
369
m = javaAgentClass.getMethod(methodname,
370
new Class<?>[] { String.class });
371
} catch (NoSuchMethodException x) {
372
// none of the methods exists so we throw the
373
// first NoSuchMethodException as per 5.0
374
throw firstExc;
375
}
376
}
377
378
// the premain method should not be required to be public,
379
// make it accessible so we can call it
380
// Note: The spec says the following:
381
// The agent class must implement a public static premain method...
382
setAccessible(m, true);
383
384
// invoke the 1 or 2-arg method
385
if (twoArgAgent) {
386
m.invoke(null, new Object[] { optionsString, this });
387
} else {
388
m.invoke(null, new Object[] { optionsString });
389
}
390
391
// don't let others access a non-public premain method
392
setAccessible(m, false);
393
}
394
395
// WARNING: the native code knows the name & signature of this method
396
private void
397
loadClassAndCallPremain( String classname,
398
String optionsString)
399
throws Throwable {
400
401
loadClassAndStartAgent( classname, "premain", optionsString );
402
}
403
404
405
// WARNING: the native code knows the name & signature of this method
406
private void
407
loadClassAndCallAgentmain( String classname,
408
String optionsString)
409
throws Throwable {
410
411
loadClassAndStartAgent( classname, "agentmain", optionsString );
412
}
413
414
// WARNING: the native code knows the name & signature of this method
415
private byte[]
416
transform( ClassLoader loader,
417
String classname,
418
Class<?> classBeingRedefined,
419
ProtectionDomain protectionDomain,
420
byte[] classfileBuffer,
421
boolean isRetransformer) {
422
TransformerManager mgr = isRetransformer?
423
mRetransfomableTransformerManager :
424
mTransformerManager;
425
if (mgr == null) {
426
return null; // no manager, no transform
427
} else {
428
return mgr.transform( loader,
429
classname,
430
classBeingRedefined,
431
protectionDomain,
432
classfileBuffer);
433
}
434
}
435
}
436
437