Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java
41153 views
1
/*
2
* Copyright (c) 2014, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @library /test/lib
27
* @summary Test that type annotations are retained after a retransform
28
* @requires vm.jvmti
29
* @modules java.base/jdk.internal.misc
30
* @modules java.base/jdk.internal.org.objectweb.asm
31
* java.instrument
32
* jdk.jartool/sun.tools.jar
33
* @run main RedefineAnnotations buildagent
34
* @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
35
*/
36
37
import static jdk.test.lib.Asserts.assertTrue;
38
import jdk.test.lib.helpers.ClassFileInstaller;
39
import java.io.FileNotFoundException;
40
import java.io.PrintWriter;
41
import java.lang.NoSuchFieldException;
42
import java.lang.NoSuchMethodException;
43
import java.lang.RuntimeException;
44
import java.lang.annotation.Annotation;
45
import java.lang.annotation.ElementType;
46
import java.lang.annotation.Retention;
47
import java.lang.annotation.RetentionPolicy;
48
import java.lang.annotation.Target;
49
import java.lang.instrument.ClassFileTransformer;
50
import java.lang.instrument.IllegalClassFormatException;
51
import java.lang.instrument.Instrumentation;
52
import java.lang.instrument.UnmodifiableClassException;
53
import java.lang.reflect.AnnotatedArrayType;
54
import java.lang.reflect.AnnotatedParameterizedType;
55
import java.lang.reflect.AnnotatedType;
56
import java.lang.reflect.AnnotatedWildcardType;
57
import java.lang.reflect.Executable;
58
import java.lang.reflect.TypeVariable;
59
import java.security.ProtectionDomain;
60
import java.util.Arrays;
61
import java.util.LinkedList;
62
import java.util.List;
63
import java.util.Map;
64
import jdk.internal.org.objectweb.asm.ClassReader;
65
import jdk.internal.org.objectweb.asm.ClassVisitor;
66
import jdk.internal.org.objectweb.asm.ClassWriter;
67
import jdk.internal.org.objectweb.asm.FieldVisitor;
68
import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
69
70
@Retention(RetentionPolicy.RUNTIME)
71
@Target(ElementType.TYPE_USE)
72
@interface TestAnn {
73
String site();
74
}
75
76
public class RedefineAnnotations {
77
static Instrumentation inst;
78
public static void premain(String agentArgs, Instrumentation inst) {
79
RedefineAnnotations.inst = inst;
80
}
81
82
static class Transformer implements ClassFileTransformer {
83
84
public byte[] asm(ClassLoader loader, String className,
85
Class<?> classBeingRedefined,
86
ProtectionDomain protectionDomain, byte[] classfileBuffer)
87
throws IllegalClassFormatException {
88
89
ClassWriter cw = new ClassWriter(0);
90
ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
91
ClassReader cr = new ClassReader(classfileBuffer);
92
cr.accept(cv, 0);
93
return cw.toByteArray();
94
}
95
96
public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
97
98
LinkedList<F> fields = new LinkedList<>();
99
100
public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
101
super(api, cv);
102
}
103
104
@Override public FieldVisitor visitField(int access, String name,
105
String desc, String signature, Object value) {
106
if (name.startsWith("dummy")) {
107
// Remove dummy field
108
fields.addLast(new F(access, name, desc, signature, value));
109
return null;
110
}
111
return cv.visitField(access, name, desc, signature, value);
112
}
113
114
@Override public void visitEnd() {
115
F f;
116
while ((f = fields.pollFirst()) != null) {
117
// Re-add dummy fields
118
cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
119
}
120
}
121
122
private class F {
123
private int access;
124
private String name;
125
private String desc;
126
private String signature;
127
private Object value;
128
F(int access, String name, String desc, String signature, Object value) {
129
this.access = access;
130
this.name = name;
131
this.desc = desc;
132
this.signature = signature;
133
this.value = value;
134
}
135
}
136
}
137
138
@Override public byte[] transform(ClassLoader loader, String className,
139
Class<?> classBeingRedefined,
140
ProtectionDomain protectionDomain, byte[] classfileBuffer)
141
throws IllegalClassFormatException {
142
143
if (className.contains("TypeAnnotatedTestClass")) {
144
try {
145
// Here we remove and re-add the dummy fields. This shuffles the constant pool
146
return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
147
} catch (Throwable e) {
148
// The retransform native code that called this method does not propagate
149
// exceptions. Instead of getting an uninformative generic error, catch
150
// problems here and print it, then exit.
151
e.printStackTrace();
152
System.exit(1);
153
}
154
}
155
return null;
156
}
157
}
158
159
private static void buildAgent() {
160
try {
161
ClassFileInstaller.main("RedefineAnnotations");
162
} catch (Exception e) {
163
throw new RuntimeException("Could not write agent classfile", e);
164
}
165
166
try {
167
PrintWriter pw = new PrintWriter("MANIFEST.MF");
168
pw.println("Premain-Class: RedefineAnnotations");
169
pw.println("Agent-Class: RedefineAnnotations");
170
pw.println("Can-Retransform-Classes: true");
171
pw.close();
172
} catch (FileNotFoundException e) {
173
throw new RuntimeException("Could not write manifest file for the agent", e);
174
}
175
176
sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
177
if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
178
throw new RuntimeException("Could not write the agent jar file");
179
}
180
}
181
182
public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
183
if (argv.length == 1 && argv[0].equals("buildagent")) {
184
buildAgent();
185
return;
186
}
187
188
if (inst == null) {
189
throw new RuntimeException("Instrumentation object was null");
190
}
191
192
RedefineAnnotations test = new RedefineAnnotations();
193
test.testTransformAndVerify();
194
}
195
196
// Class type annotations
197
private Annotation classTypeParameterTA;
198
private Annotation extendsTA;
199
private Annotation implementsTA;
200
201
// Field type annotations
202
private Annotation fieldTA;
203
private Annotation innerTA;
204
private Annotation[] arrayTA = new Annotation[4];
205
private Annotation[] mapTA = new Annotation[5];
206
207
// Method type annotations
208
private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
209
210
private void testTransformAndVerify()
211
throws NoSuchFieldException, NoSuchMethodException {
212
213
Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
214
Class<?> myClass = c;
215
216
/*
217
* Verify that the expected annotations are where they should be before transform.
218
*/
219
verifyClassTypeAnnotations(c);
220
verifyFieldTypeAnnotations(c);
221
verifyMethodTypeAnnotations(c);
222
223
try {
224
inst.addTransformer(new Transformer(), true);
225
inst.retransformClasses(myClass);
226
} catch (UnmodifiableClassException e) {
227
throw new RuntimeException(e);
228
}
229
230
/*
231
* Verify that the expected annotations are where they should be after transform.
232
* Also verify that before and after are equal.
233
*/
234
verifyClassTypeAnnotations(c);
235
verifyFieldTypeAnnotations(c);
236
verifyMethodTypeAnnotations(c);
237
}
238
239
private void verifyClassTypeAnnotations(Class c) {
240
Annotation anno;
241
242
anno = c.getTypeParameters()[0].getAnnotations()[0];
243
verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
244
classTypeParameterTA = anno;
245
246
anno = c.getAnnotatedSuperclass().getAnnotations()[0];
247
verifyTestAnn(extendsTA, anno, "extends");
248
extendsTA = anno;
249
250
anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
251
verifyTestAnn(implementsTA, anno, "implements");
252
implementsTA = anno;
253
}
254
255
private void verifyFieldTypeAnnotations(Class c)
256
throws NoSuchFieldException, NoSuchMethodException {
257
258
verifyBasicFieldTypeAnnotations(c);
259
verifyInnerFieldTypeAnnotations(c);
260
verifyArrayFieldTypeAnnotations(c);
261
verifyMapFieldTypeAnnotations(c);
262
}
263
264
private void verifyBasicFieldTypeAnnotations(Class c)
265
throws NoSuchFieldException, NoSuchMethodException {
266
267
Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
268
verifyTestAnn(fieldTA, anno, "field");
269
fieldTA = anno;
270
}
271
272
private void verifyInnerFieldTypeAnnotations(Class c)
273
throws NoSuchFieldException, NoSuchMethodException {
274
275
AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
276
Annotation anno = at.getAnnotations()[0];
277
verifyTestAnn(innerTA, anno, "inner");
278
innerTA = anno;
279
}
280
281
private void verifyArrayFieldTypeAnnotations(Class c)
282
throws NoSuchFieldException, NoSuchMethodException {
283
284
Annotation anno;
285
AnnotatedType at;
286
287
at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
288
anno = at.getAnnotations()[0];
289
verifyTestAnn(arrayTA[0], anno, "array1");
290
arrayTA[0] = anno;
291
292
for (int i = 1; i <= 3; i++) {
293
at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
294
anno = at.getAnnotations()[0];
295
verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
296
arrayTA[i] = anno;
297
}
298
}
299
300
private void verifyMapFieldTypeAnnotations(Class c)
301
throws NoSuchFieldException, NoSuchMethodException {
302
303
Annotation anno;
304
AnnotatedType atBase;
305
AnnotatedType atParameter;
306
atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
307
308
anno = atBase.getAnnotations()[0];
309
verifyTestAnn(mapTA[0], anno, "map1");
310
mapTA[0] = anno;
311
312
atParameter =
313
((AnnotatedParameterizedType) atBase).
314
getAnnotatedActualTypeArguments()[0];
315
anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
316
verifyTestAnn(mapTA[1], anno, "map2");
317
mapTA[1] = anno;
318
319
anno =
320
((AnnotatedWildcardType) atParameter).
321
getAnnotatedUpperBounds()[0].getAnnotations()[0];
322
verifyTestAnn(mapTA[2], anno, "map3");
323
mapTA[2] = anno;
324
325
atParameter =
326
((AnnotatedParameterizedType) atBase).
327
getAnnotatedActualTypeArguments()[1];
328
anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
329
verifyTestAnn(mapTA[3], anno, "map4");
330
mapTA[3] = anno;
331
332
anno =
333
((AnnotatedParameterizedType) atParameter).
334
getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
335
verifyTestAnn(mapTA[4], anno, "map5");
336
mapTA[4] = anno;
337
}
338
339
private void verifyMethodTypeAnnotations(Class c)
340
throws NoSuchFieldException, NoSuchMethodException {
341
Annotation anno;
342
Executable typeAnnotatedMethod =
343
c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
344
345
anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
346
verifyTestAnn(returnTA, anno, "return");
347
returnTA = anno;
348
349
anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
350
verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
351
methodTypeParameterTA = anno;
352
353
anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
354
verifyTestAnn(formalParameterTA, anno, "formalParameter");
355
formalParameterTA = anno;
356
357
anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
358
verifyTestAnn(throwsTA, anno, "throws");
359
throwsTA = anno;
360
}
361
362
private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
363
verifyTestAnnSite(anno, expectedSite);
364
365
// When called before transform verifyAgainst will be null, when called
366
// after transform it will be the annotation from before the transform
367
if (verifyAgainst != null) {
368
assertTrue(anno.equals(verifyAgainst),
369
"Annotations do not match before and after." +
370
" Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
371
}
372
}
373
374
private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
375
String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
376
assertTrue(testAnn.toString().equals(expectedAnn),
377
"Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
378
}
379
380
public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
381
extends @TestAnn(site="extends") Thread
382
implements @TestAnn(site="implements") Runnable {
383
384
public @TestAnn(site="field") boolean typeAnnotatedBoolean;
385
386
public
387
RedefineAnnotations.
388
@TestAnn(site="inner") TypeAnnotatedTestClass
389
typeAnnotatedInner;
390
391
public
392
@TestAnn(site="array4") boolean
393
@TestAnn(site="array1") []
394
@TestAnn(site="array2") []
395
@TestAnn(site="array3") []
396
typeAnnotatedArray;
397
398
public @TestAnn(site="map1") Map
399
<@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
400
@TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
401
402
public int dummy1;
403
public int dummy2;
404
public int dummy3;
405
406
@TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
407
typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
408
throws @TestAnn(site="throws") ClassNotFoundException {
409
410
@TestAnn(site="local_variable_type") int foo = 0;
411
throw new ClassNotFoundException();
412
}
413
414
public void run() {}
415
}
416
}
417
418