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