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