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/TransformerManager.java
38829 views
1
/*
2
* Copyright (c) 2003, 2011, 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 sun.instrument;
27
28
29
import java.lang.instrument.Instrumentation;
30
import java.lang.instrument.ClassFileTransformer;
31
import java.security.ProtectionDomain;
32
33
/*
34
* Copyright 2003 Wily Technology, Inc.
35
*/
36
37
/**
38
* Support class for the InstrumentationImpl. Manages the list of registered transformers.
39
* Keeps everything in the right order, deals with sync of the list,
40
* and actually does the calling of the transformers.
41
*/
42
public class TransformerManager
43
{
44
private class TransformerInfo {
45
final ClassFileTransformer mTransformer;
46
String mPrefix;
47
48
TransformerInfo(ClassFileTransformer transformer) {
49
mTransformer = transformer;
50
mPrefix = null;
51
}
52
53
ClassFileTransformer transformer() {
54
return mTransformer;
55
}
56
57
String getPrefix() {
58
return mPrefix;
59
}
60
61
void setPrefix(String prefix) {
62
mPrefix = prefix;
63
}
64
}
65
66
/**
67
* a given instance of this list is treated as immutable to simplify sync;
68
* we pay copying overhead whenever the list is changed rather than every time
69
* the list is referenced.
70
* The array is kept in the order the transformers are added via addTransformer
71
* (first added is 0, last added is length-1)
72
* Use an array, not a List or other Collection. This keeps the set of classes
73
* used by this code to a minimum. We want as few dependencies as possible in this
74
* code, since it is used inside the class definition system. Any class referenced here
75
* cannot be transformed by Java code.
76
*/
77
private TransformerInfo[] mTransformerList;
78
79
/***
80
* Is this TransformerManager for transformers capable of retransformation?
81
*/
82
private boolean mIsRetransformable;
83
84
TransformerManager(boolean isRetransformable) {
85
mTransformerList = new TransformerInfo[0];
86
mIsRetransformable = isRetransformable;
87
}
88
89
boolean isRetransformable() {
90
return mIsRetransformable;
91
}
92
93
public synchronized void
94
addTransformer( ClassFileTransformer transformer) {
95
TransformerInfo[] oldList = mTransformerList;
96
TransformerInfo[] newList = new TransformerInfo[oldList.length + 1];
97
System.arraycopy( oldList,
98
0,
99
newList,
100
0,
101
oldList.length);
102
newList[oldList.length] = new TransformerInfo(transformer);
103
mTransformerList = newList;
104
}
105
106
public synchronized boolean
107
removeTransformer(ClassFileTransformer transformer) {
108
boolean found = false;
109
TransformerInfo[] oldList = mTransformerList;
110
int oldLength = oldList.length;
111
int newLength = oldLength - 1;
112
113
// look for it in the list, starting at the last added, and remember
114
// where it was if we found it
115
int matchingIndex = 0;
116
for ( int x = oldLength - 1; x >= 0; x-- ) {
117
if ( oldList[x].transformer() == transformer ) {
118
found = true;
119
matchingIndex = x;
120
break;
121
}
122
}
123
124
// make a copy of the array without the matching element
125
if ( found ) {
126
TransformerInfo[] newList = new TransformerInfo[newLength];
127
128
// copy up to but not including the match
129
if ( matchingIndex > 0 ) {
130
System.arraycopy( oldList,
131
0,
132
newList,
133
0,
134
matchingIndex);
135
}
136
137
// if there is anything after the match, copy it as well
138
if ( matchingIndex < (newLength) ) {
139
System.arraycopy( oldList,
140
matchingIndex + 1,
141
newList,
142
matchingIndex,
143
(newLength) - matchingIndex);
144
}
145
mTransformerList = newList;
146
}
147
return found;
148
}
149
150
synchronized boolean
151
includesTransformer(ClassFileTransformer transformer) {
152
for (TransformerInfo info : mTransformerList) {
153
if ( info.transformer() == transformer ) {
154
return true;
155
}
156
}
157
return false;
158
}
159
160
// This function doesn't actually snapshot anything, but should be
161
// used to set a local variable, which will snapshot the transformer
162
// list because of the copying semantics of mTransformerList (see
163
// the comment for mTransformerList).
164
private TransformerInfo[]
165
getSnapshotTransformerList() {
166
return mTransformerList;
167
}
168
169
public byte[]
170
transform( ClassLoader loader,
171
String classname,
172
Class<?> classBeingRedefined,
173
ProtectionDomain protectionDomain,
174
byte[] classfileBuffer) {
175
boolean someoneTouchedTheBytecode = false;
176
177
TransformerInfo[] transformerList = getSnapshotTransformerList();
178
179
byte[] bufferToUse = classfileBuffer;
180
181
// order matters, gotta run 'em in the order they were added
182
for ( int x = 0; x < transformerList.length; x++ ) {
183
TransformerInfo transformerInfo = transformerList[x];
184
ClassFileTransformer transformer = transformerInfo.transformer();
185
byte[] transformedBytes = null;
186
187
try {
188
transformedBytes = transformer.transform( loader,
189
classname,
190
classBeingRedefined,
191
protectionDomain,
192
bufferToUse);
193
}
194
catch (Throwable t) {
195
// don't let any one transformer mess it up for the others.
196
// This is where we need to put some logging. What should go here? FIXME
197
}
198
199
if ( transformedBytes != null ) {
200
someoneTouchedTheBytecode = true;
201
bufferToUse = transformedBytes;
202
}
203
}
204
205
// if someone modified it, return the modified buffer.
206
// otherwise return null to mean "no transforms occurred"
207
byte [] result;
208
if ( someoneTouchedTheBytecode ) {
209
result = bufferToUse;
210
}
211
else {
212
result = null;
213
}
214
215
return result;
216
}
217
218
219
int
220
getTransformerCount() {
221
TransformerInfo[] transformerList = getSnapshotTransformerList();
222
return transformerList.length;
223
}
224
225
boolean
226
setNativeMethodPrefix(ClassFileTransformer transformer, String prefix) {
227
TransformerInfo[] transformerList = getSnapshotTransformerList();
228
229
for ( int x = 0; x < transformerList.length; x++ ) {
230
TransformerInfo transformerInfo = transformerList[x];
231
ClassFileTransformer aTransformer = transformerInfo.transformer();
232
233
if ( aTransformer == transformer ) {
234
transformerInfo.setPrefix(prefix);
235
return true;
236
}
237
}
238
return false;
239
}
240
241
242
String[]
243
getNativeMethodPrefixes() {
244
TransformerInfo[] transformerList = getSnapshotTransformerList();
245
String[] prefixes = new String[transformerList.length];
246
247
for ( int x = 0; x < transformerList.length; x++ ) {
248
TransformerInfo transformerInfo = transformerList[x];
249
prefixes[x] = transformerInfo.getPrefix();
250
}
251
return prefixes;
252
}
253
}
254
255