diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java index 07fdca9f741ac..bcc3efdc491d9 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassPrinterImpl.java @@ -28,6 +28,7 @@ import java.lang.constant.DirectMethodHandleDesc; import java.lang.reflect.AccessFlag; import java.util.AbstractList; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -35,7 +36,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.function.BiConsumer; import java.util.Set; import java.util.function.Consumer; @@ -75,16 +75,22 @@ public Stream walk() { } } - public static final class ListNodeImpl extends AbstractList implements ListNode { + public static sealed class ListNodeImpl extends AbstractList implements ListNode { private final Style style; private final ConstantDesc name; - private final Node[] nodes; + protected final List nodes; public ListNodeImpl(Style style, ConstantDesc name, Stream nodes) { this.style = style; this.name = name; - this.nodes = nodes.toArray(Node[]::new); + this.nodes = nodes.toList(); + } + + protected ListNodeImpl(Style style, ConstantDesc name, List nodes) { + this.style = style; + this.name = name; + this.nodes = nodes; } @Override @@ -103,18 +109,23 @@ public Style style() { @Override public Node get(int index) { - Objects.checkIndex(index, nodes.length); - return nodes[index]; + return nodes.get(index); } @Override public int size() { - return nodes.length; + return nodes.size(); } } public static final class MapNodeImpl implements MapNode { + private static final class PrivateListNodeImpl extends ListNodeImpl { + PrivateListNodeImpl(Style style, ConstantDesc name, Node... n) { + super(style, name, new ArrayList<>(List.of(n))); + } + } + private final Style style; private final ConstantDesc name; private final Map map; @@ -198,9 +209,19 @@ public Set> entrySet() { MapNodeImpl with(Node... nodes) { - for (var n : nodes) - if (n != null && map.put(n.name(), n) != null) - throw new AssertionError("Double entry of " + n.name() + " into " + name); + for (var n : nodes) { + if (n != null) { + var prev = map.putIfAbsent(n.name(), n); + if (prev != null) { + //nodes with duplicite keys are joined into a list + if (prev instanceof PrivateListNodeImpl list) { + list.nodes.add(n); + } else { + map.put(n.name(), new PrivateListNodeImpl(style, n.name(), prev, n)); + } + } + } + } return this; } } @@ -970,7 +991,7 @@ private static Node[] attributesToTree(List> attributes, Verbosity nodes.add(leaf("module main class", mmca.mainClass().name().stringValue())); case RecordAttribute ra -> nodes.add(new ListNodeImpl(BLOCK, "record components", ra.components().stream() - .map(rc -> new MapNodeImpl(BLOCK, "record") + .map(rc -> new MapNodeImpl(BLOCK, "component") .with(leafs( "name", rc.name().stringValue(), "type", rc.descriptor().stringValue())) diff --git a/test/jdk/jdk/classfile/ClassPrinterTest.java b/test/jdk/jdk/classfile/ClassPrinterTest.java index 75c1819da54c1..34163d280a0c9 100644 --- a/test/jdk/jdk/classfile/ClassPrinterTest.java +++ b/test/jdk/jdk/classfile/ClassPrinterTest.java @@ -670,13 +670,13 @@ void testPrintXmlTraceAll() throws IOException { Phee PhooBooBee - + fee LPhoo; SignatureRuntimeInvisibleTypeAnnotations LPhoo; - LBoo;FIELD + LBoo;FIELD LPhoo;flfl2.0frfl3.0 BooPhoo