Skip to content

Commit 2417382

Browse files
author
duke
committedMar 26, 2024
Automatic merge of jdk:master into master
2 parents 6ae61d7 + 8fc9097 commit 2417382

File tree

5 files changed

+198
-18
lines changed

5 files changed

+198
-18
lines changed
 

‎src/hotspot/share/classfile/classFileParser.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -3408,8 +3408,7 @@ u4 ClassFileParser::parse_classfile_record_attribute(const ClassFileStream* cons
34083408
CHECK_0);
34093409

34103410
RecordComponent* record_component =
3411-
RecordComponent::allocate(_loader_data, name_index, descriptor_index,
3412-
attributes_count, generic_sig_index,
3411+
RecordComponent::allocate(_loader_data, name_index, descriptor_index, generic_sig_index,
34133412
annotations, type_annotations, CHECK_0);
34143413
record_components->at_put(x, record_component);
34153414
} // End of component processing loop

‎src/hotspot/share/oops/recordComponent.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -33,12 +33,11 @@
3333

3434
RecordComponent* RecordComponent::allocate(ClassLoaderData* loader_data,
3535
u2 name_index, u2 descriptor_index,
36-
u2 attributes_count,
3736
u2 generic_signature_index,
3837
AnnotationArray* annotations,
3938
AnnotationArray* type_annotations, TRAPS) {
4039
return new (loader_data, size(), MetaspaceObj::RecordComponentType, THREAD)
41-
RecordComponent(name_index, descriptor_index, attributes_count,
40+
RecordComponent(name_index, descriptor_index,
4241
generic_signature_index, annotations, type_annotations);
4342
}
4443

@@ -65,7 +64,6 @@ void RecordComponent::print_value_on(outputStream* st) const {
6564
void RecordComponent::print_on(outputStream* st) const {
6665
st->print("name_index: %d", _name_index);
6766
st->print(" - descriptor_index: %d", _descriptor_index);
68-
st->print(" - attributes_count: %d", _attributes_count);
6967
if (_generic_signature_index != 0) {
7068
st->print(" - generic_signature_index: %d", _generic_signature_index);
7169
}

‎src/hotspot/share/oops/recordComponent.hpp

+3-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -36,25 +36,21 @@ class RecordComponent: public MetaspaceObj {
3636
AnnotationArray* _type_annotations;
3737
u2 _name_index;
3838
u2 _descriptor_index;
39-
u2 _attributes_count;
4039

4140
// generic_signature_index gets set if the Record component has a Signature
4241
// attribute. A zero value indicates that there was no Signature attribute.
4342
u2 _generic_signature_index;
4443

4544
public:
46-
RecordComponent(u2 name_index, u2 descriptor_index, u2 attributes_count,
47-
u2 generic_signature_index, AnnotationArray* annotations,
48-
AnnotationArray* type_annotations):
45+
RecordComponent(u2 name_index, u2 descriptor_index, u2 generic_signature_index,
46+
AnnotationArray* annotations, AnnotationArray* type_annotations):
4947
_annotations(annotations), _type_annotations(type_annotations),
5048
_name_index(name_index), _descriptor_index(descriptor_index),
51-
_attributes_count(attributes_count),
5249
_generic_signature_index(generic_signature_index) { }
5350

5451
// Allocate instance of this class
5552
static RecordComponent* allocate(ClassLoaderData* loader_data,
5653
u2 name_index, u2 descriptor_index,
57-
u2 attributes_count,
5854
u2 generic_signature_index,
5955
AnnotationArray* annotations,
6056
AnnotationArray* type_annotations, TRAPS);
@@ -69,8 +65,6 @@ class RecordComponent: public MetaspaceObj {
6965
_descriptor_index = descriptor_index;
7066
}
7167

72-
u2 attributes_count() const { return _attributes_count; }
73-
7468
u2 generic_signature_index() const { return _generic_signature_index; }
7569
void set_generic_signature_index(u2 generic_signature_index) {
7670
_generic_signature_index = generic_signature_index;

‎src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,6 @@ void JvmtiClassFileReconstituter::write_record_attribute() {
494494
RecordComponent* component = components->at(x);
495495
if (component->generic_signature_index() != 0) {
496496
length += 8; // Signature attribute size
497-
assert(component->attributes_count() > 0, "Bad component attributes count");
498497
}
499498
if (component->annotations() != nullptr) {
500499
length += 6 + component->annotations()->length();
@@ -511,7 +510,11 @@ void JvmtiClassFileReconstituter::write_record_attribute() {
511510
RecordComponent* component = components->at(i);
512511
write_u2(component->name_index());
513512
write_u2(component->descriptor_index());
514-
write_u2(component->attributes_count());
513+
u2 attributes_count = (component->generic_signature_index() != 0 ? 1 : 0)
514+
+ (component->annotations() != nullptr ? 1 : 0)
515+
+ (component->type_annotations() != nullptr ? 1 : 0);
516+
517+
write_u2(attributes_count);
515518
if (component->generic_signature_index() != 0) {
516519
write_signature_attribute(component->generic_signature_index());
517520
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*
2+
* Copyright (c) 2024, 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+
* @bug 8315575
27+
* @summary test that records with invisible annotation can be retransformed
28+
*
29+
* @library /test/lib
30+
* @run shell MakeJAR.sh retransformAgent
31+
* @run main/othervm -javaagent:retransformAgent.jar -Xlog:redefine+class=trace RetransformRecordAnnotation
32+
*/
33+
34+
import java.io.File;
35+
import java.lang.annotation.ElementType;
36+
import java.lang.annotation.Retention;
37+
import java.lang.annotation.RetentionPolicy;
38+
import java.lang.annotation.Target;
39+
import java.lang.instrument.ClassFileTransformer;
40+
import java.nio.file.Files;
41+
import java.security.ProtectionDomain;
42+
43+
public class RetransformRecordAnnotation extends AInstrumentationTestCase {
44+
45+
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
46+
@Retention(RetentionPolicy.RUNTIME)
47+
@interface RuntimeTypeAnno {}
48+
49+
@Retention(RetentionPolicy.RUNTIME)
50+
@interface RuntimeParamAnno {
51+
String s() default "foo";
52+
}
53+
54+
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
55+
@Retention(RetentionPolicy.CLASS)
56+
@interface ClassTypeAnno {}
57+
58+
@Retention(RetentionPolicy.CLASS)
59+
@interface ClassParamAnno {
60+
String s() default "bar";
61+
}
62+
63+
@RuntimeTypeAnno
64+
@RuntimeParamAnno(s = "1")
65+
public record VisibleAnnos(@RuntimeTypeAnno @RuntimeParamAnno(s = "2") Object o, Object other) {
66+
}
67+
68+
@ClassTypeAnno
69+
@ClassParamAnno(s = "3")
70+
public record InvisibleAnnos(@ClassTypeAnno @ClassParamAnno(s = "4") Object o, Object other) {
71+
}
72+
73+
@RuntimeTypeAnno
74+
@RuntimeParamAnno(s = "5")
75+
@ClassTypeAnno
76+
@ClassParamAnno(s = "6")
77+
public record MixedAnnos(@RuntimeTypeAnno @RuntimeParamAnno(s = "7")
78+
@ClassTypeAnno @ClassParamAnno(s = "8") Object o, Object other) {
79+
}
80+
81+
public static void main (String[] args) throws Throwable {
82+
ATestCaseScaffold test = new RetransformRecordAnnotation();
83+
test.beVerbose();
84+
test.runTest();
85+
}
86+
87+
private Transformer transformer;
88+
89+
public RetransformRecordAnnotation() throws Throwable {
90+
super("RetransformRecordAnnotation");
91+
}
92+
93+
private void log(Object o) {
94+
System.out.println(String.valueOf(o));
95+
}
96+
97+
// Retransforms target class using provided class bytes;
98+
private void retransform(Class targetClass, byte[] classBytes) throws Throwable {
99+
transformer.prepare(targetClass, classBytes);
100+
fInst.retransformClasses(targetClass);
101+
assertTrue(targetClass.getName() + " was not seen by transform()",
102+
transformer.getSeenClassBytes() != null);
103+
}
104+
105+
protected final void doRunTest() throws Throwable {
106+
transformer = new Transformer();
107+
fInst.addTransformer(transformer, true);
108+
109+
{
110+
log("Sanity: retransform to original class bytes");
111+
retransform(InvisibleAnnos.class, loadClassBytes(InvisibleAnnos.class));
112+
log("");
113+
}
114+
115+
// The following testcases use null as new class bytes (i.e. no transform is performed).
116+
// However, it is enough for testing purposes as the JvmtiClassFileReconstituter is still involved
117+
// in preparation of the initial class bytes.
118+
{
119+
log("Test: retransform VisibleAnnos to null");
120+
retransform(VisibleAnnos.class, null);
121+
log("");
122+
}
123+
124+
{
125+
log("Test: retransform InvisibleAnnos to null");
126+
retransform(InvisibleAnnos.class, null);
127+
log("");
128+
}
129+
130+
{
131+
log("Test: retransform MixedAnnos to null");
132+
retransform(MixedAnnos.class, null);
133+
log("");
134+
}
135+
}
136+
137+
private byte[] loadClassBytes(Class cls) throws Exception {
138+
String classFileName = cls.getName() + ".class";
139+
File classFile = new File(System.getProperty("test.classes", "."), classFileName);
140+
log("Reading test class from " + classFile);
141+
byte[] classBytes = Files.readAllBytes(classFile.toPath());
142+
log("Read " + classBytes.length + " bytes.");
143+
return classBytes;
144+
}
145+
146+
public class Transformer implements ClassFileTransformer {
147+
private String targetClassName;
148+
private byte[] seenClassBytes;
149+
private byte[] newClassBytes;
150+
151+
public Transformer() {
152+
}
153+
154+
// Prepares transformer for Instrumentation.retransformClasses.
155+
public void prepare(Class targetClass, byte[] classBytes) {
156+
targetClassName = targetClass.getName();
157+
newClassBytes = classBytes;
158+
seenClassBytes = null;
159+
}
160+
161+
byte[] getSeenClassBytes() {
162+
return seenClassBytes;
163+
}
164+
165+
public String toString() {
166+
return Transformer.this.getClass().getName();
167+
}
168+
169+
public byte[] transform(ClassLoader loader, String className,
170+
Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
171+
172+
if (className.equals(targetClassName)) {
173+
log(this + ".transform() sees '" + className
174+
+ "' of " + classfileBuffer.length + " bytes.");
175+
seenClassBytes = classfileBuffer;
176+
if (newClassBytes != null) {
177+
log(this + ".transform() sets new classbytes for '" + className
178+
+ "' of " + newClassBytes.length + " bytes.");
179+
}
180+
return newClassBytes;
181+
}
182+
183+
return null;
184+
}
185+
}
186+
}

0 commit comments

Comments
 (0)
Please sign in to comment.