Skip to content

Commit 24bc714

Browse files
committed
8355956: Prepare javap for class file format aware access flag parsing
Reviewed-by: vromero
1 parent 4cc19ba commit 24bc714

File tree

5 files changed

+89
-80
lines changed

5 files changed

+89
-80
lines changed

src/jdk.jdeps/share/classes/com/sun/tools/javap/AttributeWriter.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 2025, 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
@@ -25,15 +25,24 @@
2525

2626
package com.sun.tools.javap;
2727

28+
import java.lang.classfile.Annotation;
29+
import java.lang.classfile.Attribute;
30+
import java.lang.classfile.Attributes;
31+
import java.lang.classfile.Signature;
32+
import java.lang.classfile.TypeAnnotation;
33+
import java.lang.classfile.attribute.*;
34+
import java.lang.classfile.constantpool.ModuleEntry;
35+
import java.lang.classfile.constantpool.PoolEntry;
36+
import java.lang.classfile.constantpool.Utf8Entry;
37+
import java.lang.reflect.AccessFlag;
38+
import java.lang.reflect.ClassFileFormatVersion;
2839
import java.lang.reflect.Modifier;
2940
import java.nio.charset.StandardCharsets;
3041
import java.util.List;
3142
import java.util.Locale;
32-
import java.lang.classfile.*;
33-
import java.lang.reflect.AccessFlag;
34-
import java.lang.classfile.constantpool.*;
35-
import java.lang.classfile.attribute.*;
36-
import static java.lang.classfile.ClassFile.*;
43+
44+
import static java.lang.classfile.ClassFile.ACC_MANDATED;
45+
import static java.lang.classfile.ClassFile.ACC_SYNTHETIC;
3746
import static java.lang.classfile.attribute.StackMapFrameInfo.*;
3847
import static java.lang.classfile.instruction.CharacterRange.*;
3948

@@ -63,21 +72,21 @@ protected AttributeWriter(Context context) {
6372
options = Options.instance(context);
6473
}
6574

66-
public void write(List<Attribute<?>> attrs) {
67-
write(attrs, null);
75+
public void write(List<Attribute<?>> attrs, ClassFileFormatVersion cffv) {
76+
write(attrs, null, cffv);
6877
}
6978

70-
public void write(List<Attribute<?>> attrs, CodeAttribute lr) {
79+
public void write(List<Attribute<?>> attrs, CodeAttribute lr, ClassFileFormatVersion cffv) {
7180
if (attrs != null) {
7281
for (var attr : attrs) try {
73-
write(attr, lr);
82+
write(attr, lr, cffv);
7483
} catch (IllegalArgumentException e) {
7584
report(e);
7685
}
7786
}
7887
}
7988

80-
public void write(Attribute<?> a, CodeAttribute lr) {
89+
public void write(Attribute<?> a, CodeAttribute lr, ClassFileFormatVersion cffv) {
8190
switch (a) {
8291
case UnknownAttribute attr -> {
8392
byte[] data = attr.contents();
@@ -209,7 +218,7 @@ public void write(Attribute<?> a, CodeAttribute lr) {
209218
indent(+1);
210219
first = false;
211220
}
212-
for (var flag : maskToAccessFlagsReportUnknown(access_flags, AccessFlag.Location.INNER_CLASS)) {
221+
for (var flag : maskToAccessFlagsReportUnknown(access_flags, AccessFlag.Location.INNER_CLASS, cffv)) {
213222
if (flag.sourceModifier() && (flag != AccessFlag.ABSTRACT
214223
|| !info.has(AccessFlag.INTERFACE))) {
215224
print(Modifier.toString(flag.mask()) + " ");
@@ -494,7 +503,7 @@ public void write(Attribute<?> a, CodeAttribute lr) {
494503
println("descriptor: " + componentInfo.descriptor().stringValue());
495504
}
496505
if (options.showAllAttrs) {
497-
write(componentInfo.attributes());
506+
write(componentInfo.attributes(), cffv);
498507
println();
499508
}
500509
indent(-1);

src/jdk.jdeps/share/classes/com/sun/tools/javap/BasicWriter.java

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 2025, 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
@@ -28,6 +28,7 @@
2828
import java.io.PrintWriter;
2929
import java.lang.classfile.AccessFlags;
3030
import java.lang.reflect.AccessFlag;
31+
import java.lang.reflect.ClassFileFormatVersion;
3132
import java.lang.reflect.Modifier;
3233
import java.util.EnumMap;
3334
import java.util.Map;
@@ -44,25 +45,6 @@
4445
* deletion without notice.</b>
4546
*/
4647
public class BasicWriter {
47-
private static final Map<AccessFlag.Location, Integer> LOCATION_MASKS;
48-
49-
static {
50-
var map = new EnumMap<AccessFlag.Location, Integer>(AccessFlag.Location.class);
51-
for (var loc : AccessFlag.Location.values()) {
52-
map.put(loc, 0);
53-
}
54-
55-
for (var flag : AccessFlag.values()) {
56-
for (var loc : flag.locations()) {
57-
map.compute(loc, (_, v) -> v | flag.mask());
58-
}
59-
}
60-
61-
// Peculiarities from AccessFlag.maskToAccessFlag
62-
map.compute(AccessFlag.Location.METHOD, (_, v) -> v | Modifier.STRICT);
63-
64-
LOCATION_MASKS = map;
65-
}
6648

6749
protected BasicWriter(Context context) {
6850
lineWriter = LineWriter.instance(context);
@@ -72,15 +54,16 @@ protected BasicWriter(Context context) {
7254
throw new AssertionError();
7355
}
7456

75-
protected Set<AccessFlag> flagsReportUnknown(AccessFlags flags) {
76-
return maskToAccessFlagsReportUnknown(flags.flagsMask(), flags.location());
57+
protected Set<AccessFlag> flagsReportUnknown(AccessFlags flags, ClassFileFormatVersion cffv) {
58+
return maskToAccessFlagsReportUnknown(flags.flagsMask(), flags.location(), cffv);
7759
}
7860

79-
protected Set<AccessFlag> maskToAccessFlagsReportUnknown(int mask, AccessFlag.Location location) {
61+
protected Set<AccessFlag> maskToAccessFlagsReportUnknown(int mask, AccessFlag.Location location, ClassFileFormatVersion cffv) {
62+
// TODO pass cffv to maskToAccessFlags
8063
try {
8164
return AccessFlag.maskToAccessFlags(mask, location);
8265
} catch (IllegalArgumentException ex) {
83-
mask &= LOCATION_MASKS.get(location);
66+
mask &= location.flagsMask(cffv);
8467
report("Access Flags: " + ex.getMessage());
8568
return AccessFlag.maskToAccessFlags(mask, location);
8669
}

src/jdk.jdeps/share/classes/com/sun/tools/javap/ClassWriter.java

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 2025, 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
@@ -25,33 +25,36 @@
2525

2626
package com.sun.tools.javap;
2727

28-
import java.lang.reflect.AccessFlag;
29-
import java.net.URI;
30-
import java.text.DateFormat;
31-
import java.util.Collection;
32-
import java.util.Date;
33-
import java.util.EnumSet;
34-
import java.util.List;
35-
import java.util.Set;
36-
37-
import java.lang.constant.ClassDesc;
38-
import java.lang.reflect.Modifier;
39-
import java.util.ArrayList;
40-
import java.util.LinkedHashSet;
4128
import java.lang.classfile.AccessFlags;
4229
import java.lang.classfile.Attributes;
43-
import java.lang.classfile.ClassModel;
44-
import java.lang.classfile.ClassSignature;
4530
import java.lang.classfile.ClassFile;
46-
import static java.lang.classfile.ClassFile.*;
4731
import java.lang.classfile.ClassHierarchyResolver;
48-
import java.lang.classfile.constantpool.*;
32+
import java.lang.classfile.ClassModel;
33+
import java.lang.classfile.ClassSignature;
4934
import java.lang.classfile.FieldModel;
5035
import java.lang.classfile.MethodModel;
5136
import java.lang.classfile.MethodSignature;
5237
import java.lang.classfile.Signature;
5338
import java.lang.classfile.attribute.CodeAttribute;
5439
import java.lang.classfile.attribute.SignatureAttribute;
40+
import java.lang.classfile.constantpool.ClassEntry;
41+
import java.lang.classfile.constantpool.ConstantValueEntry;
42+
import java.lang.classfile.constantpool.PoolEntry;
43+
import java.lang.constant.ClassDesc;
44+
import java.lang.reflect.AccessFlag;
45+
import java.lang.reflect.ClassFileFormatVersion;
46+
import java.lang.reflect.Modifier;
47+
import java.net.URI;
48+
import java.text.DateFormat;
49+
import java.util.ArrayList;
50+
import java.util.Collection;
51+
import java.util.Date;
52+
import java.util.EnumSet;
53+
import java.util.LinkedHashSet;
54+
import java.util.List;
55+
import java.util.Set;
56+
57+
import static java.lang.classfile.ClassFile.*;
5558

5659
/*
5760
* The main javap class to write the contents of a class file as text.
@@ -112,6 +115,16 @@ protected void setMethod(MethodModel m) {
112115
method = m;
113116
}
114117

118+
protected ClassFileFormatVersion cffv() {
119+
var major = classModel.majorVersion();
120+
if (major < JAVA_1_VERSION || major > ClassFile.latestMajorVersion())
121+
return null;
122+
if (major >= JAVA_12_VERSION && classModel.minorVersion() != 0) {
123+
return null;
124+
}
125+
return ClassFileFormatVersion.fromMajor(major);
126+
}
127+
115128
public boolean write(ClassModel cm) {
116129
errorReported = false;
117130
setClassFile(cm);
@@ -249,7 +262,7 @@ public boolean write(ClassModel cm) {
249262
println("}");
250263

251264
if (options.verbose) {
252-
attrWriter.write(classModel.attributes());
265+
attrWriter.write(classModel.attributes(), cffv());
253266
}
254267

255268
if (options.verify) {
@@ -266,10 +279,10 @@ public boolean write(ClassModel cm) {
266279
}
267280
// where
268281

269-
private static final ClassFile VERIFIER = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(
282+
private static final ClassFile VERIFIER = ClassFile.of(ClassHierarchyResolverOption.of(
270283
ClassHierarchyResolver.defaultResolver().orElse(new ClassHierarchyResolver() {
271284
@Override
272-
public ClassHierarchyResolver.ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
285+
public ClassHierarchyInfo getClassInfo(ClassDesc classDesc) {
273286
// mark all unresolved classes as interfaces to exclude them from assignability verification
274287
return ClassHierarchyInfo.ofInterface();
275288
}
@@ -419,7 +432,7 @@ protected void writeField(FieldModel f) {
419432
return;
420433

421434
var flags = f.flags();
422-
writeModifiers(flagsReportUnknown(flags).stream().filter(fl -> fl.sourceModifier())
435+
writeModifiers(flagsReportUnknown(flags, cffv()).stream().filter(fl -> fl.sourceModifier())
423436
.map(fl -> Modifier.toString(fl.mask())).toList());
424437
print(() -> sigPrinter.print(
425438
f.findAttribute(Attributes.signature())
@@ -448,11 +461,11 @@ protected void writeField(FieldModel f) {
448461

449462
if (options.verbose)
450463
writeList(String.format("flags: (0x%04x) ", flags.flagsMask()),
451-
flagsReportUnknown(flags).stream().map(fl -> "ACC_" + fl.name()).toList(),
464+
flagsReportUnknown(flags, cffv()).stream().map(fl -> "ACC_" + fl.name()).toList(),
452465
"\n");
453466

454467
if (options.showAllAttrs) {
455-
attrWriter.write(f.attributes());
468+
attrWriter.write(f.attributes(), cffv());
456469
showBlank = true;
457470
}
458471

@@ -480,7 +493,7 @@ protected void writeMethod(MethodModel m) {
480493
int flags = m.flags().flagsMask();
481494

482495
var modifiers = new ArrayList<String>();
483-
for (var f : flagsReportUnknown(m.flags()))
496+
for (var f : flagsReportUnknown(m.flags(), cffv()))
484497
if (f.sourceModifier()) modifiers.add(Modifier.toString(f.mask()));
485498

486499
String name = "???";
@@ -563,7 +576,7 @@ protected void writeMethod(MethodModel m) {
563576
StringBuilder sb = new StringBuilder();
564577
String sep = "";
565578
sb.append(String.format("flags: (0x%04x) ", flags));
566-
for (var f : flagsReportUnknown(m.flags())) {
579+
for (var f : flagsReportUnknown(m.flags(), cffv())) {
567580
sb.append(sep).append("ACC_").append(f.name());
568581
sep = ", ";
569582
}
@@ -573,7 +586,7 @@ protected void writeMethod(MethodModel m) {
573586
var code = (CodeAttribute)m.code().orElse(null);
574587

575588
if (options.showAllAttrs) {
576-
attrWriter.write(m.attributes());
589+
attrWriter.write(m.attributes(), cffv());
577590
} else if (code != null && options.showDisassembled) {
578591
codeWriter.writeMinimal(code);
579592
}
@@ -786,7 +799,7 @@ else switch (c) {
786799
}
787800

788801
private Set<String> getClassModifiers(AccessFlags flags) {
789-
var flagSet = flagsReportUnknown(flags);
802+
var flagSet = flagsReportUnknown(flags, cffv());
790803
Set<AccessFlag> set;
791804
if (flagSet.contains(AccessFlag.INTERFACE)) {
792805
set = EnumSet.copyOf(flagSet);
@@ -797,18 +810,18 @@ private Set<String> getClassModifiers(AccessFlags flags) {
797810
return getModifiers(set);
798811
}
799812

800-
private static Set<String> getModifiers(Set<java.lang.reflect.AccessFlag> flags) {
813+
private static Set<String> getModifiers(Set<AccessFlag> flags) {
801814
Set<String> s = new LinkedHashSet<>();
802815
for (var f : flags)
803816
if (f.sourceModifier()) s.add(Modifier.toString(f.mask()));
804817
return s;
805818
}
806819

807820
private Set<String> getClassFlags(AccessFlags flags) {
808-
return getFlags(flags.flagsMask(), flagsReportUnknown(flags));
821+
return getFlags(flags.flagsMask(), flagsReportUnknown(flags, cffv()));
809822
}
810823

811-
private static Set<String> getFlags(int mask, Set<java.lang.reflect.AccessFlag> flags) {
824+
private static Set<String> getFlags(int mask, Set<AccessFlag> flags) {
812825
Set<String> s = new LinkedHashSet<>();
813826
for (var f: flags) {
814827
s.add("ACC_" + f.name());

src/jdk.jdeps/share/classes/com/sun/tools/javap/CodeWriter.java

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 2025, 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
@@ -25,15 +25,18 @@
2525

2626
package com.sun.tools.javap;
2727

28-
import java.lang.classfile.*;
28+
import java.lang.classfile.Attributes;
29+
import java.lang.classfile.ClassFile;
30+
import java.lang.classfile.Instruction;
31+
import java.lang.classfile.MethodModel;
32+
import java.lang.classfile.Opcode;
33+
import java.lang.classfile.attribute.CodeAttribute;
34+
import java.lang.classfile.constantpool.PoolEntry;
35+
import java.lang.classfile.instruction.*;
2936
import java.util.ArrayList;
3037
import java.util.List;
31-
3238
import java.util.Locale;
3339
import java.util.stream.Collectors;
34-
import java.lang.classfile.constantpool.*;
35-
import java.lang.classfile.attribute.CodeAttribute;
36-
import java.lang.classfile.instruction.*;
3740

3841
/*
3942
* Write the contents of a Code attribute.
@@ -277,14 +280,14 @@ private void writeVerboseMode(CodeAttribute attr) {
277280
writeVerboseHeader(attr);
278281
writeInstrs(attr);
279282
writeExceptionTable(attr);
280-
attrWriter.write(attr.attributes(), attr);
283+
attrWriter.write(attr.attributes(), attr, classWriter.cffv());
281284
}
282285

283286
private void writeLineAndLocalVariableTables(CodeAttribute attr) {
284287
attr.findAttribute(Attributes.lineNumberTable())
285-
.ifPresent(a -> attrWriter.write(a, attr));
288+
.ifPresent(a -> attrWriter.write(a, attr, classWriter.cffv()));
286289
attr.findAttribute(Attributes.localVariableTable())
287-
.ifPresent(a -> attrWriter.write(a, attr));
290+
.ifPresent(a -> attrWriter.write(a, attr, classWriter.cffv()));
288291
}
289292

290293
private AttributeWriter attrWriter;

test/langtools/tools/javap/UndefinedAccessFlagTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, 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
@@ -22,7 +22,8 @@
2222
*/
2323

2424
/*
25-
* @test 8333748
25+
* @test
26+
* @bug 8333748 8349536
2627
* @summary javap should not fail if reserved access flag bits are set to 1
2728
* @library /tools/lib
2829
* @modules jdk.jdeps/com.sun.tools.javap
@@ -91,7 +92,7 @@ void test(TestLocation location) throws Throwable {
9192
});
9293
case InnerClassesAttribute attr when location == TestLocation.INNER_CLASS -> cb
9394
.with(InnerClassesAttribute.of(attr.classes().stream()
94-
.map(ic -> InnerClassInfo.of(ic.innerClass(), ic.outerClass(), ic.innerName(), ic.flagsMask() | 0x0020))
95+
.map(ic -> InnerClassInfo.of(ic.innerClass(), ic.outerClass(), ic.innerName(), ic.flagsMask() | ACC_SUPER))
9596
.toList()));
9697
default -> cb.with(ce);
9798
}

0 commit comments

Comments
 (0)