iterator() {
* @param bootstrapMethods the array of bootstrap methods
*/
public final void setBootstrapMethods(final BootstrapMethod[] bootstrapMethods) {
- this.bootstrapMethods = bootstrapMethods;
+ this.bootstrapMethods = bootstrapMethods != null ? bootstrapMethods : BootstrapMethod.EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java
index a61e1d75390..037f3908379 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassFormatException.java
@@ -47,12 +47,10 @@ public ClassFormatException(final String message) {
/**
* Constructs a new instance with the specified detail message and cause.
- *
- * Note that the detail message associated with {@code cause} is not automatically incorporated in this runtime exception's detail message.
*
* @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method).
- * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that
- * the cause is nonexistent or unknown.)
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that
+ * the cause is nonexistent or unknown.
* @since 6.0
*/
public ClassFormatException(final String message, final Throwable cause) {
@@ -63,8 +61,8 @@ public ClassFormatException(final String message, final Throwable cause) {
* Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the
* class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables.
*
- * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that the
- * cause is nonexistent or unknown.)
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that the
+ * cause is nonexistent or unknown.
* @since 6.7.0
*/
public ClassFormatException(final Throwable cause) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java
index c9daaeabf9b..0dbda722ec4 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java
@@ -37,7 +37,7 @@
* appropriate exception is propagated back to the caller.
*
* The structure and the names comply, except for a few conveniences, exactly with the
- * JVM specification 1.0. See this paper for further details about
+ * JVM specification 1.0. See this paper for further details about
* the structure of a bytecode file.
*/
public final class ClassParser {
@@ -57,7 +57,7 @@ public final class ClassParser {
private Field[] fields; // class fields, i.e., its variables
private Method[] methods; // methods defined in the class
private Attribute[] attributes; // attributes defined in the class
- private final boolean isZip; // Loaded from zip file
+ private final boolean isZip; // Loaded from ZIP file
/**
* Parses class from the given stream.
@@ -91,7 +91,7 @@ public ClassParser(final String fileName) {
/**
* Parses class from given .class file in a ZIP-archive
*
- * @param zipFile zip file name
+ * @param zipFile ZIP file name
* @param fileName file name
*/
public ClassParser(final String zipFile, final String fileName) {
@@ -104,7 +104,7 @@ public ClassParser(final String zipFile, final String fileName) {
/**
* Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods,
* fields and commands. A ClassFormatException is raised, if the file is not a valid .class file. (This does
- * not include verification of the byte code as it is performed by the java interpreter).
+ * not include verification of the byte code as it is performed by the Java interpreter).
*
* @return Class object representing the parsed class file
* @throws IOException if an I/O error occurs.
@@ -151,11 +151,11 @@ public JavaClass parse() throws IOException, ClassFormatException {
// for (int i=0; i < u.length; i++)
// System.err.println("WARNING: " + u[i]);
// Everything should have been read now
- // if(file.available() > 0) {
+ // if (file.available() > 0) {
// int bytes = file.available();
// byte[] buf = new byte[bytes];
// file.read(buf);
- // if(!(isZip && (buf.length == 1))) {
+ // if (!(isZip && (buf.length == 1))) {
// System.err.println("WARNING: Trailing garbage at end of " + fileName);
// System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf));
// }
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java
index 498a8c71b18..7573a5412e7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class represents a chunk of Java byte code contained in a method. It is instantiated by the
@@ -59,7 +60,7 @@
* @see CodeException
* @see LineNumberTable
* @see LocalVariableTable
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class Code extends Attribute {
@@ -93,7 +94,7 @@ public Code(final Code code) {
code = new byte[codeLength]; // Read byte code
file.readFully(code);
/*
- * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch()
+ * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch ()
* block.
*/
final int exceptionTableLength = file.readUnsignedShort();
@@ -107,7 +108,7 @@ public Code(final Code code) {
final int attributesCount = file.readUnsignedShort();
attributes = new Attribute[attributesCount];
for (int i = 0; i < attributesCount; i++) {
- attributes[i] = Attribute.readAttribute(file, constantPool);
+ attributes[i] = readAttribute(file, constantPool);
}
/*
* Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal
@@ -131,8 +132,8 @@ public Code(final int nameIndex, final int length, final int maxStack, final int
super(Const.ATTR_CODE, nameIndex, length, constantPool);
this.maxStack = Args.requireU2(maxStack, "maxStack");
this.maxLocals = Args.requireU2(maxLocals, "maxLocals");
- this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY;
- this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
+ this.code = Utils.createEmptyArrayIfNull(code);
+ this.exceptionTable = Utils.createEmptyArrayIfNull(exceptionTable, CodeException[].class);
Args.requireU2(this.exceptionTable.length, "exceptionTable.length");
this.attributes = attributes != null ? attributes : EMPTY_ARRAY;
super.setLength(calculateLength()); // Adjust length
@@ -263,6 +264,20 @@ public LocalVariableTable getLocalVariableTable() {
return null;
}
+ /**
+ * Gets the local variable type table attribute {@link LocalVariableTypeTable}.
+ * @return LocalVariableTypeTable of Code, if it has one, null otherwise.
+ * @since 6.10.0
+ */
+ public LocalVariableTypeTable getLocalVariableTypeTable() {
+ for (final Attribute attribute : attributes) {
+ if (attribute instanceof LocalVariableTypeTable) {
+ return (LocalVariableTypeTable) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @return Number of local variables.
*/
@@ -277,6 +292,20 @@ public int getMaxStack() {
return maxStack;
}
+ /**
+ * Finds the attribute of {@link StackMap} instance.
+ * @return StackMap of Code, if it has one, else null.
+ * @since 6.8.0
+ */
+ public StackMap getStackMap() {
+ for (final Attribute attribute : attributes) {
+ if (attribute instanceof StackMap) {
+ return (StackMap) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @param attributes the attributes to set for this Code
*/
@@ -289,7 +318,7 @@ public void setAttributes(final Attribute[] attributes) {
* @param code byte code
*/
public void setCode(final byte[] code) {
- this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY;
+ this.code = Utils.createEmptyArrayIfNull(code);
super.setLength(calculateLength()); // Adjust length
}
@@ -297,7 +326,7 @@ public void setCode(final byte[] code) {
* @param exceptionTable exception table
*/
public void setExceptionTable(final CodeException[] exceptionTable) {
- this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
+ this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_ARRAY;
super.setLength(calculateLength()); // Adjust length
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java
index ee224e6b348..b8bf109239e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -52,19 +52,19 @@
*
*
* @see Code
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class CodeException implements Cloneable, Node {
/**
* Empty array.
*/
- static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {};
+ static final CodeException[] EMPTY_ARRAY = {};
/** Range in the code the exception handler. */
private int startPc;
- /** active. startPc is inclusive, endPc exclusive. */
+ /** Active. startPc is inclusive, endPc exclusive. */
private int endPc;
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java
index 885e1b599eb..9b3d6f31e17 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -32,30 +32,29 @@
* in the constant pool of a class file. The classes keep closely to
* the JVM specification.
*
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class Constant implements Cloneable, Node {
- private static BCELComparator bcelComparator = new BCELComparator() {
+ static final Constant[] EMPTY_ARRAY = {};
+
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final Constant THIS = (Constant) o1;
- final Constant THAT = (Constant) o2;
- return Objects.equals(THIS.toString(), THAT.toString());
+ public boolean equals(final Constant a, final Constant b) {
+ return a == b || a != null && b != null && Objects.equals(a.toString(), b.toString());
}
@Override
- public int hashCode(final Object o) {
- final Constant THIS = (Constant) o;
- return THIS.toString().hashCode();
+ public int hashCode(final Constant o) {
+ return o != null ? Objects.hashCode(o.toString()) : 0;
}
};
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
@@ -113,7 +112,7 @@ public static Constant readConstant(final DataInput dataInput) throws IOExceptio
/**
* @param comparator Comparison strategy object
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -148,7 +147,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -174,7 +173,7 @@ public Constant copy() {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof Constant && bcelComparator.equals(this, (Constant) obj);
}
/**
@@ -185,7 +184,7 @@ public final byte getTag() {
}
/**
- * Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of
+ * Returns value as defined by given BCELComparator strategy. By default return the hash code of the result of
* toString().
*
* @see Object#hashCode()
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java
index 71fd91b249a..51113a1aeaa 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,11 +28,11 @@
/**
* Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants.
*
- * @see ConstantFieldref
- * @see ConstantMethodref
- * @see ConstantInterfaceMethodref
- * @see ConstantInvokeDynamic
- * @LastModified: Jun 2019
+ * @see ConstantFieldref
+ * @see ConstantMethodref
+ * @see ConstantInterfaceMethodref
+ * @see ConstantInvokeDynamic
+ * @LastModified: Sept 2025
*/
public abstract class ConstantCP extends Constant {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java
index ebb3d0af46a..14b43937c92 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,8 +29,8 @@
/**
* This class is derived from the abstract {@link Constant} and represents a reference to a Double object.
*
- * @see Constant
- * @LastModified: Jun 2019
+ * @see Constant
+ * @LastModified: Sept 2025
*/
public final class ConstantDouble extends Constant implements ConstantObject {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java
index 9c30c9e4fdb..e86bbb94e66 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,8 +29,8 @@
/**
* This class is derived from the abstract {@link Constant} and represents a reference to a float object.
*
- * @see Constant
- * @LastModified: Jun 2019
+ * @see Constant
+ * @LastModified: Sept 2025
*/
public final class ConstantFloat extends Constant implements ConstantObject {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java
index cabd2e15b03..20c0717acb6 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,8 +29,8 @@
/**
* This class is derived from the abstract {@link Constant} and represents a reference to an int object.
*
- * @see Constant
- * @LastModified: Jun 2019
+ * @see Constant
+ * @LastModified: Sept 2025
*/
public final class ConstantInteger extends Constant implements ConstantObject {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java
index c1e683abadb..6936162c264 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,8 +29,8 @@
/**
* This class is derived from the abstract {@link Constant} and represents a reference to a long object.
*
- * @see Constant
- * @LastModified: Jan 2020
+ * @see Constant
+ * @LastModified: Sept 2025
*/
public final class ConstantLong extends Constant implements ConstantObject {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java
index cb28f7dacb8..ab187b7e4f8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java
@@ -29,7 +29,10 @@
public interface ConstantObject {
/**
- * @return object representing the constant, e.g., Long for ConstantLong
+ * Gets the object representing the constant, e.g., Long for ConstantLong.
+ *
+ * @param constantPool the constant.
+ * @return object representing the constant, e.g., Long for ConstantLong.
*/
- Object getConstantValue(ConstantPool cp);
+ Object getConstantValue(ConstantPool constantPool);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java
index 5fb4ef1b080..ae1e3977c99 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -35,7 +35,7 @@
*
* @see Constant
* @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ConstantPool implements Cloneable, Node, Iterable {
@@ -73,7 +73,7 @@ private static String escape(final String str) {
* @param constantPool Array of constants
*/
public ConstantPool(final Constant[] constantPool) {
- this.constantPool = constantPool;
+ setConstantPool(constantPool);
}
/**
@@ -88,6 +88,7 @@ public ConstantPool(final DataInput input) throws IOException {
constantPool = new Constant[constantPoolCount];
/*
* constantPool[0] is unused by the compiler and may be used freely by the implementation.
+ * constantPool[0] is currently unused by the implementation.
*/
for (int i = 1; i < constantPoolCount; i++) {
constantPool[i] = Constant.readConstant(input);
@@ -288,7 +289,7 @@ public T getConstant(final int index, final byte tag) throw
*/
public T getConstant(final int index, final byte tag, final Class castTo) throws ClassFormatException {
final T c = getConstant(index);
- if (c.getTag() != tag) {
+ if (c == null || c.getTag() != tag) {
throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c);
}
return c;
@@ -313,16 +314,18 @@ public T getConstant(final int index, final Class castTo
throw new ClassFormatException("Invalid constant pool reference at index: " + index +
". Expected " + castTo + " but was " + constantPool[index].getClass());
}
- // Previous check ensures this won't throw a ClassCastException
- final T c = castTo.cast(constantPool[index]);
- if (c == null
- // the 0th element is always null
- && index != 0) {
+ if (index > 1) {
final Constant prev = constantPool[index - 1];
- if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) {
- throw new ClassFormatException("Constant pool at index " + index + " is null.");
+ if (prev != null && (prev.getTag() == Const.CONSTANT_Double || prev.getTag() == Const.CONSTANT_Long)) {
+ throw new ClassFormatException("Constant pool at index " + index + " is invalid. The index is unused due to the preceeding "
+ + Const.getConstantName(prev.getTag()) + ".");
}
}
+ // Previous check ensures this won't throw a ClassCastException
+ final T c = castTo.cast(constantPool[index]);
+ if (c == null) {
+ throw new ClassFormatException("Constant pool at index " + index + " is null.");
+ }
return c;
}
@@ -402,7 +405,7 @@ public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException
* @return Length of constant pool.
*/
public int getLength() {
- return constantPool == null ? 0 : constantPool.length;
+ return constantPool.length;
}
@Override
@@ -421,7 +424,7 @@ public void setConstant(final int index, final Constant constant) {
* @param constantPool
*/
public void setConstantPool(final Constant[] constantPool) {
- this.constantPool = constantPool;
+ this.constantPool = constantPool != null ? constantPool : Constant.EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java
index ec875554c1a..90e45c807e5 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -36,11 +36,11 @@
* The following system properties govern caching this class performs.
*
*
- * - {@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
+ *
- {@link #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
* disabled.
- * - {@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
+ *
- {@link #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
* disables caching. Values larger than this are not cached.
- * - {@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
+ * - {@link #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
*
*
* Here is a sample Maven invocation with caching disabled:
@@ -58,11 +58,11 @@
*
*
* @see Constant
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ConstantUtf8 extends Constant {
- private static class Cache {
+ private static final class Cache {
private static final boolean BCEL_STATISTICS = false;
private static final int MAX_ENTRIES = 20000;
@@ -82,7 +82,7 @@ protected boolean removeEldestEntry(final Map.Entry eldest
private static final int MAX_ENTRY_SIZE = 200;
static boolean isEnabled() {
- return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
+ return MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
}
}
@@ -117,6 +117,11 @@ static synchronized void clearStats() {
hits = considered = skipped = created = 0;
}
+ // Avoid Spotbugs complaint about Write to static field
+ private static void countCreated() {
+ created++;
+ }
+
/**
* Gets a new or cached instance of the given value.
*
@@ -203,7 +208,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) {
ConstantUtf8(final DataInput dataInput) throws IOException {
super(Const.CONSTANT_Utf8);
value = dataInput.readUTF();
- created++;
+ countCreated();
}
/**
@@ -212,7 +217,7 @@ public ConstantUtf8(final ConstantUtf8 constantUtf8) {
public ConstantUtf8(final String value) {
super(Const.CONSTANT_Utf8);
this.value = Objects.requireNonNull(value, "value");
- created++;
+ countCreated();
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
index 311e9a33fa3..143c2a25544 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java
@@ -56,7 +56,7 @@ public ConstantValue(final ConstantValue c) {
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Name index in constant pool
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
index 90841d96081..c561afe33c5 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java
@@ -59,7 +59,7 @@ public Deprecated(final int nameIndex, final int length, final byte[] bytes, fin
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
index 3c475891acd..934b608d6ac 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -22,12 +22,13 @@
import java.util.Objects;
import java.util.Stack;
import java.util.stream.Stream;
+import jdk.xml.internal.Utils;
/**
- * Traverses a JavaClass with another Visitor object 'piggy-backed' that is
- * applied to all components of a JavaClass object. I.e. this class supplies the
- * traversal strategy, other classes can make use of it.
+ * Traverses a JavaClass with another Visitor object 'piggy-backed' that is applied to all components of a JavaClass
+ * object. I.e. this class supplies the traversal strategy, other classes can make use of it.
*
+ * @LastModified: Sept 2025
*/
public class DescendingVisitor implements Visitor {
private final JavaClass clazz;
@@ -46,7 +47,7 @@ public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
}
private void accept(final E[] node) {
- Stream.of(node).forEach(e -> e.accept(this));
+ Utils.streamOfIfNonNull(node).forEach(e -> e.accept(this));
}
/**
@@ -507,6 +508,21 @@ public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
stack.pop();
}
+ @Override
+ public void visitRecord(final Record record) {
+ stack.push(record);
+ record.accept(visitor);
+ accept(record.getComponents());
+ stack.pop();
+ }
+
+ @Override
+ public void visitRecordComponent(final RecordComponentInfo recordComponentInfo) {
+ stack.push(recordComponentInfo);
+ recordComponentInfo.accept(visitor);
+ stack.pop();
+ }
+
@Override
public void visitSignature(final Signature attribute) {
stack.push(attribute);
@@ -531,6 +547,20 @@ public void visitStackMap(final StackMap table) {
@Override
public void visitStackMapEntry(final StackMapEntry var) {
+ stack.push(var);
+ var.accept(visitor);
+ accept(var.getTypesOfLocals());
+ accept(var.getTypesOfStackItems());
+ stack.pop();
+ }
+
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param var object to visit
+ * @since 6.8.0
+ */
+ @Override
+ public void visitStackMapType(final StackMapType var) {
stack.push(var);
var.accept(visitor);
stack.pop();
@@ -549,4 +579,5 @@ public void visitUnknown(final Unknown attribute) {
attribute.accept(visitor);
stack.pop();
}
+
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
index 5c3d9b3172b..d87307c0e7d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -50,7 +50,7 @@
*}
*
* @since 6.0
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class ElementValue {
@@ -67,6 +67,7 @@ public abstract class ElementValue {
public static final byte PRIMITIVE_LONG = 'J';
public static final byte PRIMITIVE_SHORT = 'S';
public static final byte PRIMITIVE_BOOLEAN = 'Z';
+ static final ElementValue[] EMPTY_ARRAY = {};
/**
* Reads an {@code element_value} as an {@code ElementValue}.
@@ -124,7 +125,7 @@ public static ElementValue readElementValue(final DataInput input, final Constan
final int numArrayVals = input.readUnsignedShort();
final ElementValue[] evalues = new ElementValue[numArrayVals];
for (int j = 0; j < numArrayVals; j++) {
- evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting);
+ evalues[j] = readElementValue(input, cpool, arrayNesting);
}
return new ArrayElementValue(ARRAY, evalues, cpool);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
index 826ba41af70..db33c871656 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java
@@ -315,6 +315,15 @@ public void visitStackMap(final StackMap obj) {
public void visitStackMapEntry(final StackMapEntry obj) {
}
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param obj object to visit
+ * @since 6.8.0
+ */
+ @Override
+ public void visitStackMapType(final StackMapType obj) {
+ }
+
@Override
public void visitSynthetic(final Synthetic obj) {
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
index 90eaa3eb062..1b6004b3740 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class represents the table of exceptions that are thrown by a method. This attribute may be used once per
@@ -43,7 +44,7 @@
* }
*
* @see Code
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ExceptionTable extends Attribute {
@@ -60,7 +61,7 @@ public ExceptionTable(final ExceptionTable c) {
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -85,7 +86,7 @@ public ExceptionTable(final ExceptionTable c) {
*/
public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) {
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
- this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
+ this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable);
Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length");
}
@@ -156,7 +157,7 @@ public int getNumberOfExceptions() {
* length.
*/
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
- this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
+ this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
index 7e6ccb2ecb5..8ffc796a0ea 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java
@@ -42,45 +42,37 @@ public final class Field extends FieldOrMethod {
*/
public static final Field[] EMPTY_ARRAY = {};
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final Field THIS = (Field) o1;
- final Field THAT = (Field) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final Field a, final Field b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final Field THIS = (Field) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final Field o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * Empty array.
+ * @return Comparison strategy object.
*/
- static final Field[] EMPTY_FIELD_ARRAY = {};
-
- /**
- * @return Comparison strategy object
- */
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
- * @param file Input stream
+ * @param file Input stream.
*/
Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
super(file, constantPool);
@@ -133,7 +125,7 @@ public Field copy(final ConstantPool constantPool) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof Field && bcelComparator.equals(this, (Field) obj);
}
/**
@@ -149,14 +141,16 @@ public ConstantValue getConstantValue() {
}
/**
+ * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2
+ *
* @return type of field
*/
public Type getType() {
- return Type.getReturnType(getSignature());
+ return Type.getType(getSignature());
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
* signature.
*
* @see Object#hashCode()
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
index 1daa6a62fd5..679d5a9eb7c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,7 +28,7 @@
/**
* Abstract super class for fields and methods.
*
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node {
@@ -72,7 +72,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -88,7 +88,7 @@ protected FieldOrMethod(final DataInput file, final ConstantPool constantPool) t
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -137,7 +137,7 @@ protected FieldOrMethod copy_(final ConstantPool constantPool) {
Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool));
return c;
} catch (final CloneNotSupportedException e) {
- throw new IllegalStateException(e);
+ throw new UnsupportedOperationException(e);
}
}
@@ -152,10 +152,8 @@ public final void dump(final DataOutputStream file) throws IOException {
file.writeShort(name_index);
file.writeShort(signature_index);
file.writeShort(attributes_count);
- if (attributes != null) {
- for (final Attribute attribute : attributes) {
- attribute.dump(file);
- }
+ for (final Attribute attribute : attributes) {
+ attribute.dump(file);
}
}
@@ -171,6 +169,22 @@ public AnnotationEntry[] getAnnotationEntries() {
return annotationEntries;
}
+ /**
+ * Gets attribute for given tag.
+ * @return Attribute for given tag, null if not found.
+ * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
+ * @since 6.10.0
+ */
+ @SuppressWarnings("unchecked")
+ public final T getAttribute(final byte tag) {
+ for (final Attribute attribute : getAttributes()) {
+ if (attribute.getTag() == tag) {
+ return (T) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @return Collection of object attributes.
*/
@@ -221,7 +235,7 @@ public final int getNameIndex() {
}
/**
- * @return String representation of object's type signature (java style)
+ * @return String representation of object's type signature (Java style)
*/
public final String getSignature() {
return constant_pool.getConstantUtf8(signature_index).getBytes();
@@ -238,8 +252,8 @@ public final int getSignatureIndex() {
* @param attributes Collection of object attributes.
*/
public final void setAttributes(final Attribute[] attributes) {
- this.attributes = attributes;
- this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field
+ this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
+ this.attributes_count = this.attributes.length; // init deprecated field
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
index d77582815b7..82900dcca10 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java
@@ -41,7 +41,7 @@ public final class InnerClass implements Cloneable, Node {
private int innerAccessFlags;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
index 2295ca5c625..b61be1effa0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java
@@ -42,7 +42,7 @@ public final class InnerClasses extends Attribute implements Iterable iterator() {
* @param innerClasses the array of inner classes
*/
public void setInnerClasses(final InnerClass[] innerClasses) {
- this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
+ this.innerClasses = innerClasses != null ? innerClasses : EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java
new file mode 100644
index 00000000000..eaf1da2d2e1
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java
@@ -0,0 +1,53 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.bcel.internal.classfile;
+
+/**
+ * Thrown when the BCEL attempts to read a class file and determines that a class is malformed or otherwise cannot be interpreted as a class file.
+ *
+ * @since 6.8.0
+ */
+public class InvalidMethodSignatureException extends ClassFormatException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new instance with the specified invalid signature as the message.
+ *
+ * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method.
+ */
+ public InvalidMethodSignatureException(final String signature) {
+ super(signature);
+ }
+
+ /**
+ * Constructs a new instance with the specified invalid signature as the message and a cause.
+ *
+ * @param signature The invalid signature is saved for later retrieval by the {@link #getMessage()} method.
+ * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that
+ * the cause is nonexistent or unknown.
+ */
+ public InvalidMethodSignatureException(final String signature, final Throwable cause) {
+ super(signature, cause);
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
index d6c4cfa6a07..1b0e2ed1ce0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/JavaClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -38,6 +38,7 @@
import com.sun.org.apache.bcel.internal.util.BCELComparator;
import com.sun.org.apache.bcel.internal.util.ClassQueue;
import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
+import jdk.xml.internal.Utils;
/**
* Represents a Java class, i.e., the data structures, constant pool, fields, methods and commands contained in a Java
@@ -46,7 +47,7 @@
* classes should see the ClassGen class.
*
* @see com.sun.org.apache.bcel.internal.generic.ClassGen
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable {
@@ -67,26 +68,23 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
public static final byte HEAP = 1;
public static final byte FILE = 2;
public static final byte ZIP = 3;
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final JavaClass THIS = (JavaClass) o1;
- final JavaClass THAT = (JavaClass) o2;
- return Objects.equals(THIS.getClassName(), THAT.getClassName());
+ public boolean equals(final JavaClass a, final JavaClass b) {
+ return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName());
}
@Override
- public int hashCode(final Object o) {
- final JavaClass THIS = (JavaClass) o;
- return THIS.getClassName().hashCode();
+ public int hashCode(final JavaClass o) {
+ return o != null ? Objects.hashCode(o.getClassName()) : 0;
}
};
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
@@ -100,9 +98,9 @@ private static String indent(final Object obj) {
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -128,8 +126,10 @@ public static void setComparator(final BCELComparator comparator) {
private boolean isAnonymous;
private boolean isNested;
+ private boolean isRecord;
private boolean computedNestedTypeStatus;
+ private boolean computedRecord;
/**
* In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any
@@ -177,17 +177,15 @@ public JavaClass(final int classNameIndex, final int superclassNameIndex, final
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
final ConstantPool constantPool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes, final byte source) {
super(accessFlags);
- if (interfaces == null) {
- interfaces = Const.EMPTY_INT_ARRAY;
- }
+ interfaces = Utils.createEmptyArrayIfNull(interfaces);
if (attributes == null) {
attributes = Attribute.EMPTY_ARRAY;
}
if (fields == null) {
- fields = Field.EMPTY_FIELD_ARRAY;
+ fields = Field.EMPTY_ARRAY;
}
if (methods == null) {
- methods = Method.EMPTY_METHOD_ARRAY;
+ methods = Method.EMPTY_ARRAY;
}
this.classNameIndex = classNameIndex;
this.superclassNameIndex = superclassNameIndex;
@@ -254,6 +252,19 @@ public int compareTo(final JavaClass obj) {
return getClassName().compareTo(obj.getClassName());
}
+ private void computeIsRecord() {
+ if (computedRecord) {
+ return;
+ }
+ for (final Attribute attribute : this.attributes) {
+ if (attribute instanceof Record) {
+ isRecord = true;
+ break;
+ }
+ }
+ this.computedRecord = true;
+ }
+
private void computeNestedTypeStatus() {
if (computedNestedTypeStatus) {
return;
@@ -384,11 +395,51 @@ public void dump(final String fileName) throws IOException {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof JavaClass && bcelComparator.equals(this, (JavaClass) obj);
+ }
+
+ /**
+ * Finds a visible field by name and type in this class and its super classes.
+ * @param fieldName the field name to find
+ * @param fieldType the field type to find
+ * @return field matching given name and type, null if field is not found or not accessible from this class.
+ * @throws ClassNotFoundException
+ * @since 6.8.0
+ */
+ public Field findField(final String fieldName, final Type fieldType) throws ClassNotFoundException {
+ for (final Field field : fields) {
+ if (field.getName().equals(fieldName)) {
+ final Type fType = Type.getType(field.getSignature());
+ /*
+ * TODO: Check if assignment compatibility is sufficient. What does Sun do?
+ */
+ if (fType.equals(fieldType)) {
+ return field;
+ }
+ }
+ }
+
+ final JavaClass superclass = getSuperClass();
+ if (superclass != null && !"java.lang.Object".equals(superclass.getClassName())) {
+ final Field f = superclass.findField(fieldName, fieldType);
+ if (f != null && (f.isPublic() || f.isProtected() || !f.isPrivate() && packageName.equals(superclass.getPackageName()))) {
+ return f;
+ }
+ }
+ final JavaClass[] implementedInterfaces = getInterfaces();
+ if (implementedInterfaces != null) {
+ for (final JavaClass implementedInterface : implementedInterfaces) {
+ final Field f = implementedInterface.findField(fieldName, fieldType);
+ if (f != null) {
+ return f;
+ }
+ }
+ }
+ return null;
}
/**
- * Get all interfaces implemented by this JavaClass (transitively).
+ * Gets all interfaces implemented by this JavaClass (transitively).
*
* @throws ClassNotFoundException if any of the class's superclasses or interfaces can't be found.
*/
@@ -409,7 +460,7 @@ public JavaClass[] getAllInterfaces() throws ClassNotFoundException {
queue.enqueue(iface);
}
}
- return allInterfaces.toArray(JavaClass.EMPTY_ARRAY);
+ return allInterfaces.toArray(EMPTY_ARRAY);
}
/**
@@ -424,6 +475,22 @@ public AnnotationEntry[] getAnnotationEntries() {
return annotations;
}
+ /**
+ * Gets attribute for given tag.
+ * @return Attribute for given tag, null if not found.
+ * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values.
+ * @since 6.10.0
+ */
+ @SuppressWarnings("unchecked")
+ public final T getAttribute(final byte tag) {
+ for (final Attribute attribute : getAttributes()) {
+ if (attribute.getTag() == tag) {
+ return (T) attribute;
+ }
+ }
+ return null;
+ }
+
/**
* @return Attributes of the class.
*/
@@ -495,7 +562,7 @@ public String[] getInterfaceNames() {
}
/**
- * Get interfaces directly implemented by this JavaClass.
+ * Gets interfaces directly implemented by this JavaClass.
*
* @throws ClassNotFoundException if any of the class's interfaces can't be found.
*/
@@ -587,7 +654,7 @@ public String getSourceFilePath() {
}
/**
- * @return the superclass for this JavaClass object, or null if this is java.lang.Object
+ * @return the superclass for this JavaClass object, or null if this is {@link Object}
* @throws ClassNotFoundException if the superclass can't be found
*/
public JavaClass getSuperClass() throws ClassNotFoundException {
@@ -607,12 +674,12 @@ public JavaClass[] getSuperClasses() throws ClassNotFoundException {
for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) {
allSuperClasses.add(clazz);
}
- return allSuperClasses.toArray(JavaClass.EMPTY_ARRAY);
+ return allSuperClasses.toArray(EMPTY_ARRAY);
}
/**
- * returns the super class name of this class. In the case that this class is java.lang.Object, it will return itself
- * (java.lang.Object). This is probably incorrect but isn't fixed at this time to not break existing clients.
+ * returns the super class name of this class. In the case that this class is {@link Object}, it will return itself
+ * ({@link Object}). This is probably incorrect but isn't fixed at this time to not break existing clients.
*
* @return Superclass name.
*/
@@ -628,7 +695,7 @@ public int getSuperclassNameIndex() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name.
*
* @see Object#hashCode()
*/
@@ -645,7 +712,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep
if (!inter.isInterface()) {
throw new IllegalArgumentException(inter.getClassName() + " is no interface");
}
- if (this.equals(inter)) {
+ if (equals(inter)) {
return true;
}
final JavaClass[] superInterfaces = getAllInterfaces();
@@ -664,7 +731,7 @@ public boolean implementationOf(final JavaClass inter) throws ClassNotFoundExcep
* @throws ClassNotFoundException if superclasses or superinterfaces of this object can't be found
*/
public final boolean instanceOf(final JavaClass superclass) throws ClassNotFoundException {
- if (this.equals(superclass)) {
+ if (equals(superclass)) {
return true;
}
for (final JavaClass clazz : getSuperClasses()) {
@@ -698,6 +765,17 @@ public final boolean isNested() {
return this.isNested;
}
+ /**
+ * Tests whether this class was declared as a record
+ *
+ * @return true if a record attribute is present, false otherwise.
+ * @since 6.9.0
+ */
+ public boolean isRecord() {
+ computeIsRecord();
+ return this.isRecord;
+ }
+
public final boolean isSuper() {
return (super.getAccessFlags() & Const.ACC_SUPER) != 0;
}
@@ -706,7 +784,7 @@ public final boolean isSuper() {
* @param attributes .
*/
public void setAttributes(final Attribute[] attributes) {
- this.attributes = attributes;
+ this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
}
/**
@@ -734,11 +812,11 @@ public void setConstantPool(final ConstantPool constantPool) {
* @param fields .
*/
public void setFields(final Field[] fields) {
- this.fields = fields;
+ this.fields = fields != null ? fields : Field.EMPTY_ARRAY;
}
/**
- * Set File name of class, aka SourceFile attribute value
+ * Sets File name of class, aka SourceFile attribute value
*/
public void setFileName(final String fileName) {
this.fileName = fileName;
@@ -748,14 +826,14 @@ public void setFileName(final String fileName) {
* @param interfaceNames .
*/
public void setInterfaceNames(final String[] interfaceNames) {
- this.interfaceNames = interfaceNames;
+ this.interfaceNames = Utils.createEmptyArrayIfNull(interfaceNames, String[].class);
}
/**
* @param interfaces .
*/
public void setInterfaces(final int[] interfaces) {
- this.interfaces = interfaces;
+ this.interfaces = Utils.createEmptyArrayIfNull(interfaces);
}
/**
@@ -769,7 +847,7 @@ public void setMajor(final int major) {
* @param methods .
*/
public void setMethods(final Method[] methods) {
- this.methods = methods;
+ this.methods = methods != null ? methods : Method.EMPTY_ARRAY;
}
/**
@@ -787,7 +865,7 @@ public void setRepository(final com.sun.org.apache.bcel.internal.util.Repository
}
/**
- * Set absolute path to file this class was read from.
+ * Sets absolute path to file this class was read from.
*/
public void setSourceFileName(final String sourceFileName) {
this.sourceFileName = sourceFileName;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
index 4380d04bc06..dc41ad065f8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java
@@ -40,11 +40,11 @@ public final class LineNumber implements Cloneable, Node {
/** Program Counter (PC) corresponds to line */
private int startPc;
- /** number in source file */
+ /** Number in source file */
private int lineNumber;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
index 6251fc514cc..96541f309bd 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -36,7 +36,7 @@
*
* @see Code
* @see LineNumber
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public final class LineNumberTable extends Attribute implements Iterable {
@@ -44,7 +44,7 @@ public final class LineNumberTable extends Attribute implements Iterable
+ * Note that both objects use the same references (shallow copy). Use copy() for a physical copy.
+ *
*/
public LineNumberTable(final LineNumberTable c) {
this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool());
@@ -190,7 +191,7 @@ public Iterator iterator() {
* @param lineNumberTable the line number entries for this table
*/
public void setLineNumberTable(final LineNumber[] lineNumberTable) {
- this.lineNumberTable = lineNumberTable;
+ this.lineNumberTable = lineNumberTable != null ? lineNumberTable : LineNumber.EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
index fd56e14a539..26fde9bdbdf 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTable.java
@@ -40,10 +40,12 @@
*/
public class LocalVariableTable extends Attribute implements Iterable {
+ private static final LocalVariable[] EMPTY_ARRAY = {};
+
private LocalVariable[] localVariableTable; // variables
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -68,7 +70,7 @@ public class LocalVariableTable extends Attribute implements Iterable iterator() {
}
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
- this.localVariableTable = localVariableTable;
+ this.localVariableTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
index 08868a82de8..ce327e20f52 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LocalVariableTypeTable.java
@@ -63,14 +63,14 @@
*/
public class LocalVariableTypeTable extends Attribute implements Iterable {
+ private static final LocalVariable[] EMPTY_ARRAY = {};
+
private LocalVariable[] localVariableTypeTable; // variables
LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException {
this(nameIdx, len, (LocalVariable[]) null, cpool);
-
final int localVariableTypeTableLength = input.readUnsignedShort();
localVariableTypeTable = new LocalVariable[localVariableTypeTableLength];
-
for (int i = 0; i < localVariableTypeTableLength; i++) {
localVariableTypeTable[i] = new LocalVariable(input, cpool);
}
@@ -97,7 +97,6 @@ public void accept(final Visitor v) {
@Override
public Attribute copy(final ConstantPool constantPool) {
final LocalVariableTypeTable c = (LocalVariableTypeTable) clone();
-
c.localVariableTypeTable = new LocalVariable[localVariableTypeTable.length];
Arrays.setAll(c.localVariableTypeTable, i -> localVariableTypeTable[i].copy());
c.setConstantPool(constantPool);
@@ -119,7 +118,6 @@ public final LocalVariable getLocalVariable(final int index) {
return variable;
}
}
-
return null;
}
@@ -137,7 +135,7 @@ public Iterator iterator() {
}
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
- this.localVariableTypeTable = localVariableTable;
+ this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
}
/**
@@ -146,15 +144,12 @@ public final void setLocalVariableTable(final LocalVariable[] localVariableTable
@Override
public final String toString() {
final StringBuilder buf = new StringBuilder();
-
for (int i = 0; i < localVariableTypeTable.length; i++) {
buf.append(localVariableTypeTable[i].toStringShared(true));
-
if (i < localVariableTypeTable.length - 1) {
buf.append('\n');
}
}
-
return buf.toString();
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
index ba2623eec08..643c820f366 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Method.java
@@ -40,42 +40,34 @@ public final class Method extends FieldOrMethod {
*/
public static final Method[] EMPTY_ARRAY = {};
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final Method THIS = (Method) o1;
- final Method THAT = (Method) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final Method a, final Method b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final Method THIS = (Method) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final Method o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * Empty array.
+ * @return Comparison strategy object.
*/
- static final Method[] EMPTY_METHOD_ARRAY = {};
-
- /**
- * @return Comparison strategy object
- */
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
- // annotations defined on the parameters of a method
+ /** Annotations defined on the parameters of a method. */
private ParameterAnnotationEntry[] parameterAnnotationEntries;
/**
@@ -85,7 +77,7 @@ public Method() {
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -142,7 +134,7 @@ public Method copy(final ConstantPool constantPool) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof Method && bcelComparator.equals(this, (Method) obj);
}
/**
@@ -189,7 +181,7 @@ public LineNumberTable getLineNumberTable() {
}
/**
- * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute.
+ * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code attribute.
*/
public LocalVariableTable getLocalVariableTable() {
final Code code = getCode();
@@ -199,6 +191,19 @@ public LocalVariableTable getLocalVariableTable() {
return code.getLocalVariableTable();
}
+ /**
+ * Gets the local variable type table attribute {@link LocalVariableTypeTable}.
+ * @return LocalVariableTypeTable of code attribute if any, i.e. the call is forwarded to the Code attribute.
+ * @since 6.10.0
+ */
+ public LocalVariableTypeTable getLocalVariableTypeTable() {
+ final Code code = getCode();
+ if (code == null) {
+ return null;
+ }
+ return code.getLocalVariableTypeTable();
+ }
+
/**
* @return Annotations on the parameters of a method
* @since 6.0
@@ -218,7 +223,7 @@ public Type getReturnType() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR
* signature.
*
* @see Object#hashCode()
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
index ffc1a20f80a..865e154d334 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java
@@ -29,6 +29,9 @@
/**
* Entry of the parameters table.
+ *
+ * Implements {@link Node} as of 6.7.0.
+ *
*
* @see The class File Format :
* The MethodParameters Attribute
@@ -46,7 +49,7 @@ public MethodParameter() {
}
/**
- * Construct object from input stream.
+ * Constructs an instance from a DataInput.
*
* @param input Input stream
* @throws IOException if an I/O error occurs.
@@ -75,7 +78,7 @@ public MethodParameter copy() {
}
/**
- * Dump object to file stream on binary format.
+ * Dumps object to file stream on binary format.
*
* @param file Output file stream
* @throws IOException if an I/O error occurs.
@@ -94,7 +97,10 @@ public int getNameIndex() {
}
/**
- * Returns the name of the parameter.
+ * Gets the name of the parameter.
+ *
+ * @param constantPool The pool to query.
+ * @return Constant from the given pool.
*/
public String getParameterName(final ConstantPool constantPool) {
if (nameIndex == 0) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
index 5b5d1d77f6f..2f5bffd8d3c 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java
@@ -42,13 +42,12 @@ public class MethodParameters extends Attribute implements Iterable parameters[i].copy());
c.setConstantPool(constantPool);
return c;
@@ -96,6 +94,6 @@ public Iterator iterator() {
}
public void setParameters(final MethodParameter[] parameters) {
- this.parameters = parameters;
+ this.parameters = parameters != null ? parameters : EMPTY_ARRAY;
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
index 00eebe18245..addf6f0aea3 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Module.java
@@ -44,19 +44,27 @@ public final class Module extends Attribute {
*/
public static final String EXTENSION = ".jmod";
+ private static String getClassNameAtIndex(final ConstantPool cp, final int index, final boolean compactClassName) {
+ final String className = cp.getConstantString(index, Const.CONSTANT_Class);
+ if (compactClassName) {
+ return Utility.compactClassName(className, false);
+ }
+ return className;
+ }
private final int moduleNameIndex;
private final int moduleFlags;
- private final int moduleVersionIndex;
+ private final int moduleVersionIndex;
private ModuleRequires[] requiresTable;
private ModuleExports[] exportsTable;
private ModuleOpens[] opensTable;
private final int usesCount;
private final int[] usesIndex;
+
private ModuleProvides[] providesTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -113,8 +121,6 @@ public void accept(final Visitor v) {
v.visitModule(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this attribute
*/
@@ -186,6 +192,25 @@ public ModuleExports[] getExportsTable() {
return exportsTable;
}
+ /**
+ * Gets flags for this module.
+ * @return module flags
+ * @since 6.10.0
+ */
+ public int getModuleFlags() {
+ return moduleFlags;
+ }
+
+ /**
+ * Gets module name.
+ * @param cp Array of constants
+ * @return module name
+ * @since 6.10.0
+ */
+ public String getModuleName(final ConstantPool cp) {
+ return cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module);
+ }
+
/**
* @return table of provided interfaces
* @see ModuleOpens
@@ -210,6 +235,31 @@ public ModuleRequires[] getRequiresTable() {
return requiresTable;
}
+ /**
+ * Gets the array of class names for this module's uses.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @param compactClassName false for original constant pool value, true to replace '/' with '.'
+ * @return array of used class names
+ * @since 6.10.0
+ */
+ public String[] getUsedClassNames(final ConstantPool constantPool, final boolean compactClassName) {
+ final String[] usedClassNames = new String[usesCount];
+ for (int i = 0; i < usesCount; i++) {
+ usedClassNames[i] = getClassNameAtIndex(constantPool, usesIndex[i], compactClassName);
+ }
+ return usedClassNames;
+ }
+
+ /**
+ * Gets version for this module.
+ * @param cp Array of constants
+ * @return version from constant pool, "0" if version index is 0
+ * @since 6.10.0
+ */
+ public String getVersion(final ConstantPool cp) {
+ return moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
+ }
+
/**
* @return String representation, i.e., a list of packages.
*/
@@ -218,9 +268,9 @@ public String toString() {
final ConstantPool cp = super.getConstantPool();
final StringBuilder buf = new StringBuilder();
buf.append("Module:\n");
- buf.append(" name: ").append(Utility.pathToPackage(cp.getConstantString(moduleNameIndex, Const.CONSTANT_Module))).append("\n");
+ buf.append(" name: ").append(Utility.pathToPackage(getModuleName(cp))).append("\n");
buf.append(" flags: ").append(String.format("%04x", moduleFlags)).append("\n");
- final String version = moduleVersionIndex == 0 ? "0" : cp.getConstantString(moduleVersionIndex, Const.CONSTANT_Utf8);
+ final String version = getVersion(cp);
buf.append(" version: ").append(version).append("\n");
buf.append(" requires(").append(requiresTable.length).append("):\n");
@@ -240,8 +290,8 @@ public String toString() {
buf.append(" uses(").append(usesIndex.length).append("):\n");
for (final int index : usesIndex) {
- final String className = cp.getConstantString(index, Const.CONSTANT_Class);
- buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
+ final String className = getClassNameAtIndex(cp, index, true);
+ buf.append(" ").append(className).append("\n");
}
buf.append(" provides(").append(providesTable.length).append("):\n");
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
index 8a97f4b6d08..f92f508b862 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleExports.java
@@ -36,13 +36,17 @@
*/
public final class ModuleExports implements Cloneable, Node {
+ private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) {
+ return constantPool.getConstantString(index, Const.CONSTANT_Module);
+ }
private final int exportsIndex; // points to CONSTANT_Package_info
private final int exportsFlags;
private final int exportsToCount;
+
private final int[] exportsToIndex; // points to CONSTANT_Module_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -68,8 +72,6 @@ public void accept(final Visitor v) {
v.visitModuleExports(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the flags for this ModuleExports.
+ * @return the exportsFlags
+ * @since 6.10.0
+ */
+ public int getExportsFlags() {
+ return exportsFlags;
+ }
+
+ /**
+ * Gets the exported package name.
+ * @param constantPool the constant pool from the ClassFile
+ * @return the exported package name
+ * @since 6.10.0
+ */
+ public String getPackageName(final ConstantPool constantPool) {
+ return constantPool.constantToString(exportsIndex, Const.CONSTANT_Package);
+ }
+
+ /**
+ * Gets an array of module names for this ModuleExports.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return array of module names following 'exports to'
+ * @since 6.10.0
+ */
+ public String[] getToModuleNames(final ConstantPool constantPool) {
+ final String[] toModuleNames = new String[exportsToCount];
+ for (int i = 0; i < exportsToCount; i++) {
+ toModuleNames[i] = getToModuleNameAtIndex(constantPool, exportsToIndex[i]);
+ }
+ return toModuleNames;
+ }
+
/**
* @return String representation
*/
@@ -110,13 +145,13 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String packageName = constantPool.constantToString(exportsIndex, Const.CONSTANT_Package);
- buf.append(Utility.compactClassName(packageName, false));
+ final String packageName = getPackageName(constantPool);
+ buf.append(packageName);
buf.append(", ").append(String.format("%04x", exportsFlags));
buf.append(", to(").append(exportsToCount).append("):\n");
for (final int index : exportsToIndex) {
- final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
- buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
+ final String moduleName = getToModuleNameAtIndex(constantPool, index);
+ buf.append(" ").append(moduleName).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
index a6ffd882862..b73bd01f794 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleMainClass.java
@@ -39,7 +39,7 @@ public final class ModuleMainClass extends Attribute {
private int mainClassIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
index 06b404df72b..388370a45e7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleOpens.java
@@ -36,13 +36,17 @@
*/
public final class ModuleOpens implements Cloneable, Node {
+ private static String getToModuleNameAtIndex(final ConstantPool constantPool, final int index) {
+ return constantPool.getConstantString(index, Const.CONSTANT_Module);
+ }
private final int opensIndex; // points to CONSTANT_Package_info
private final int opensFlags;
private final int opensToCount;
+
private final int[] opensToIndex; // points to CONSTANT_Module_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -68,8 +72,6 @@ public void accept(final Visitor v) {
v.visitModuleOpens(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -97,6 +99,39 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the flags for this ModuleOpens.
+ * @return the opensFlags
+ * @since 6.10.0
+ */
+ public int getOpensFlags() {
+ return opensFlags;
+ }
+
+ /**
+ * Gets the opened package name.
+ * @param constantPool the constant pool from the ClassFile
+ * @return the opened package name
+ * @since 6.10.0
+ */
+ public String getPackageName(final ConstantPool constantPool) {
+ return constantPool.constantToString(opensIndex, Const.CONSTANT_Package);
+ }
+
+ /**
+ * Gets an array of module names for this ModuleOpens.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return array of module names following 'opens to'
+ * @since 6.10.0
+ */
+ public String[] getToModuleNames(final ConstantPool constantPool) {
+ final String[] toModuleNames = new String[opensToCount];
+ for (int i = 0; i < opensToCount; i++) {
+ toModuleNames[i] = getToModuleNameAtIndex(constantPool, opensToIndex[i]);
+ }
+ return toModuleNames;
+ }
+
/**
* @return String representation
*/
@@ -110,13 +145,13 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String packageName = constantPool.constantToString(opensIndex, Const.CONSTANT_Package);
- buf.append(Utility.compactClassName(packageName, false));
+ final String packageName = getPackageName(constantPool);
+ buf.append(packageName);
buf.append(", ").append(String.format("%04x", opensFlags));
buf.append(", to(").append(opensToCount).append("):\n");
for (final int index : opensToIndex) {
- final String moduleName = constantPool.getConstantString(index, Const.CONSTANT_Module);
- buf.append(" ").append(Utility.compactClassName(moduleName, false)).append("\n");
+ final String moduleName = getToModuleNameAtIndex(constantPool, index);
+ buf.append(" ").append(moduleName).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
index 96367e02d2d..f48587e5455 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModulePackages.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,20 +27,21 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class is derived from Attribute and represents the list of packages that are exported or opened by the
* Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure.
*
* @see Attribute
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class ModulePackages extends Attribute {
private int[] packageIndexTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -65,7 +66,7 @@ public final class ModulePackages extends Attribute {
*/
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) {
super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool);
- this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
+ this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable);
Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length");
}
@@ -145,7 +146,7 @@ public String[] getPackageNames() {
* @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length.
*/
public void setPackageIndexTable(final int[] packageIndexTable) {
- this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY;
+ this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
index f6c6058dfbb..490e9cd5d44 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java
@@ -36,12 +36,20 @@
*/
public final class ModuleProvides implements Cloneable, Node {
+ private static String getImplementationClassNameAtIndex(final ConstantPool constantPool, final int index, final boolean compactClassName) {
+ final String className = constantPool.getConstantString(index, Const.CONSTANT_Class);
+ if (compactClassName) {
+ return Utility.compactClassName(className, false);
+ }
+ return className;
+ }
private final int providesIndex; // points to CONSTANT_Class_info
private final int providesWithCount;
+
private final int[] providesWithIndex; // points to CONSTANT_Class_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -66,8 +74,6 @@ public void accept(final Visitor v) {
v.visitModuleProvides(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -94,6 +100,31 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the array of implementation class names for this ModuleProvides.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @param compactClassName false for original constant pool value, true to replace '/' with '.'
+ * @return array of implementation class names
+ * @since 6.10.0
+ */
+ public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) {
+ final String[] implementationClassNames = new String[providesWithCount];
+ for (int i = 0; i < providesWithCount; i++) {
+ implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName);
+ }
+ return implementationClassNames;
+ }
+
+ /**
+ * Gets the interface name for this ModuleProvides.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return interface name
+ * @since 6.10.0
+ */
+ public String getInterfaceName(final ConstantPool constantPool) {
+ return constantPool.constantToString(providesIndex, Const.CONSTANT_Class);
+ }
+
/**
* @return String representation
*/
@@ -107,12 +138,12 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class);
- buf.append(Utility.compactClassName(interfaceName, false));
+ final String interfaceName = getInterfaceName(constantPool);
+ buf.append(interfaceName);
buf.append(", with(").append(providesWithCount).append("):\n");
for (final int index : providesWithIndex) {
- final String className = constantPool.getConstantString(index, Const.CONSTANT_Class);
- buf.append(" ").append(Utility.compactClassName(className, false)).append("\n");
+ final String className = getImplementationClassNameAtIndex(constantPool, index, true);
+ buf.append(" ").append(className).append("\n");
}
return buf.substring(0, buf.length() - 1); // remove the last newline
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
index c9c26c20649..3149a18290b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java
@@ -41,7 +41,7 @@ public final class ModuleRequires implements Cloneable, Node {
private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O Exception occurs in readUnsignedShort
@@ -63,8 +63,6 @@ public void accept(final Visitor v) {
v.visitModuleRequires(this);
}
- // TODO add more getters and setters?
-
/**
* @return deep copy of this object
*/
@@ -89,6 +87,35 @@ public void dump(final DataOutputStream file) throws IOException {
file.writeShort(requiresVersionIndex);
}
+ /**
+ * Gets the module name from the constant pool.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return module name
+ * @since 6.10.0
+ */
+ public String getModuleName(final ConstantPool constantPool) {
+ return constantPool.constantToString(requiresIndex, Const.CONSTANT_Module);
+ }
+
+ /**
+ * Gets the flags for this ModuleRequires.
+ * @return the requiresFlags
+ * @since 6.10.0
+ */
+ public int getRequiresFlags() {
+ return requiresFlags;
+ }
+
+ /**
+ * Gets the required version from the constant pool.
+ * @param constantPool Array of constants usually obtained from the ClassFile object
+ * @return required version, "0" if version index is 0.
+ * @since 6.10.0
+ */
+ public String getVersion(final ConstantPool constantPool) {
+ return requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
+ }
+
/**
* @return String representation
*/
@@ -102,10 +129,10 @@ public String toString() {
*/
public String toString(final ConstantPool constantPool) {
final StringBuilder buf = new StringBuilder();
- final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module);
- buf.append(Utility.compactClassName(moduleName, false));
+ final String moduleName = getModuleName(constantPool);
+ buf.append(moduleName);
buf.append(", ").append(String.format("%04x", requiresFlags));
- final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8);
+ final String version = getVersion(constantPool);
buf.append(", ").append(version);
return buf.toString();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
index 05d982ca6e8..261f57d98a8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.util.Args;
+import jdk.xml.internal.Utils;
/**
* This class is derived from Attribute and records the classes and interfaces that are authorized to claim
@@ -34,14 +35,14 @@
* ClassFile structure.
*
* @see Attribute
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class NestMembers extends Attribute {
private int[] classes;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool
* @param length Content length in bytes
@@ -66,7 +67,7 @@ public final class NestMembers extends Attribute {
*/
public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) {
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
- this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
+ this.classes = Utils.createEmptyArrayIfNull(classes);
Args.requireU2(this.classes.length, "classes.length");
}
@@ -146,7 +147,7 @@ public int getNumberClasses() {
* @param classes the list of class indexes Also redefines number_of_classes according to table length.
*/
public void setClasses(final int[] classes) {
- this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY;
+ this.classes = Utils.createEmptyArrayIfNull(classes);
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
index c0395732d79..792ef31cb72 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java
@@ -26,5 +26,5 @@
*/
public interface Node {
- void accept(Visitor obj);
+ void accept(Visitor visitor);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
index 9b1dd4c7b41..b7b5e1f1d99 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java
@@ -38,7 +38,7 @@ public final class PMGClass extends Attribute {
private int pmgIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
index a3070fa7e0c..6ebe60c8049 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java
@@ -37,22 +37,28 @@ public class ParameterAnnotationEntry implements Node {
static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
- public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
+ public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attributes) {
+ if (attributes == null) {
+ return EMPTY_ARRAY;
+ }
// Find attributes that contain parameter annotation data
- final List accumulatedAnnotations = new ArrayList<>(attrs.length);
- for (final Attribute attribute : attrs) {
+ final List accumulatedAnnotations = new ArrayList<>(attributes.length);
+ for (final Attribute attribute : attributes) {
if (attribute instanceof ParameterAnnotations) {
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute;
- Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
+ final ParameterAnnotationEntry[] parameterAnnotationEntries = runtimeAnnotations.getParameterAnnotationEntries();
+ if (parameterAnnotationEntries != null) {
+ Collections.addAll(accumulatedAnnotations, parameterAnnotationEntries);
+ }
}
}
- return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY);
+ return accumulatedAnnotations.toArray(EMPTY_ARRAY);
}
private final AnnotationEntry[] annotationTable;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param input Input stream
* @throws IOException if an I/O error occurs.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
index 4817793120f..1e056b5d4f8 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java
@@ -34,10 +34,14 @@
*/
public abstract class ParameterAnnotations extends Attribute implements Iterable {
+ private static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
+
/** Table of parameter annotations */
private ParameterAnnotationEntry[] parameterAnnotationTable;
/**
+ * Constructs a new instance.
+ *
* @param parameterAnnotationType the subclass type of the parameter annotation
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
@@ -55,6 +59,8 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable
}
/**
+ * Constructs a new instance.
+ *
* @param parameterAnnotationType the subclass type of the parameter annotation
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
@@ -120,6 +126,6 @@ public Iterator iterator() {
* @param parameterAnnotationTable the entries to set in this parameter annotation
*/
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) {
- this.parameterAnnotationTable = parameterAnnotationTable;
+ this.parameterAnnotationTable = parameterAnnotationTable != null ? parameterAnnotationTable : EMPTY_ARRAY;
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java
new file mode 100644
index 00000000000..f59cfa37ca4
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java
@@ -0,0 +1,153 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.sun.org.apache.bcel.internal.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.sun.org.apache.bcel.internal.Const;
+import com.sun.org.apache.bcel.internal.util.Args;
+
+/**
+ * Extends {@link Attribute} and records the classes and
+ * interfaces that are authorized to claim membership in the nest hosted by the
+ * current class or interface. There may be at most one Record attribute in a
+ * ClassFile structure.
+ *
+ * @see Attribute
+ * @since 6.9.0
+ */
+public final class Record extends Attribute {
+
+ private static final RecordComponentInfo[] EMPTY_RCI_ARRAY = {};
+
+ private static RecordComponentInfo[] readComponents(final DataInput input, final ConstantPool constantPool)
+ throws IOException {
+ final int classCount = input.readUnsignedShort();
+ final RecordComponentInfo[] components = new RecordComponentInfo[classCount];
+ for (int i = 0; i < classCount; i++) {
+ components[i] = new RecordComponentInfo(input, constantPool);
+ }
+ return components;
+ }
+
+ private RecordComponentInfo[] components;
+
+ /**
+ * Constructs object from input stream.
+ *
+ * @param nameIndex Index in constant pool
+ * @param length Content length in bytes
+ * @param input Input stream
+ * @param constantPool Array of constants
+ * @throws IOException if an I/O error occurs.
+ */
+ Record(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
+ throws IOException {
+ this(nameIndex, length, readComponents(input, constantPool), constantPool);
+ }
+
+ /**
+ * Constructs a new instance using components.
+ *
+ * @param nameIndex Index in constant pool
+ * @param length Content length in bytes
+ * @param classes Array of Record Component Info elements
+ * @param constantPool Array of constants
+ */
+ public Record(final int nameIndex, final int length, final RecordComponentInfo[] classes,
+ final ConstantPool constantPool) {
+ super(Const.ATTR_RECORD, nameIndex, length, constantPool);
+ this.components = classes != null ? classes : EMPTY_RCI_ARRAY;
+ Args.requireU2(this.components.length, "attributes.length");
+ }
+
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitly
+ * defined by the contents of a Java class. For example, the hierarchy of methods,
+ * fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ */
+ @Override
+ public void accept(final Visitor v) {
+ v.visitRecord(this);
+ }
+
+ /**
+ * Copies this instance and its components.
+ *
+ * @return a deep copy of this instance and its components.
+ */
+ @Override
+ public Attribute copy(final ConstantPool constantPool) {
+ final Record c = (Record) clone();
+ if (components.length > 0) {
+ c.components = components.clone();
+ }
+ c.setConstantPool(constantPool);
+ return c;
+ }
+
+ /**
+ * Dumps this instance into a file stream in binary format.
+ *
+ * @param file output stream.
+ * @throws IOException if an I/O error occurs.
+ */
+ @Override
+ public void dump(final DataOutputStream file) throws IOException {
+ super.dump(file);
+ file.writeShort(components.length);
+ for (final RecordComponentInfo component : components) {
+ component.dump(file);
+ }
+ }
+
+ /**
+ * Gets all the record components.
+ *
+ * @return array of Record Component Info elements.
+ */
+ public RecordComponentInfo[] getComponents() {
+ return components;
+ }
+
+ /**
+ * Converts this instance to a String suitable for debugging.
+ *
+ * @return String a String suitable for debugging.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("Record(");
+ buf.append(components.length);
+ buf.append("):\n");
+ for (final RecordComponentInfo component : components) {
+ buf.append(" ").append(component.toString()).append("\n");
+ }
+ return buf.substring(0, buf.length() - 1); // remove the last newline
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java
new file mode 100644
index 00000000000..3679647d409
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java
@@ -0,0 +1,139 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
+
+import java.io.DataInput;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import com.sun.org.apache.bcel.internal.Const;
+
+/**
+ * Record component info from a record. Instances from this class maps
+ * every component from a given record.
+ *
+ * @see
+ * The Java Virtual Machine Specification, Java SE 14 Edition, Records (preview)
+ * @since 6.9.0
+ */
+public class RecordComponentInfo implements Node {
+
+ private final int index;
+ private final int descriptorIndex;
+ private final Attribute[] attributes;
+ private final ConstantPool constantPool;
+
+ /**
+ * Constructs a new instance from an input stream.
+ *
+ * @param input Input stream
+ * @param constantPool Array of constants
+ * @throws IOException if an I/O error occurs.
+ */
+ public RecordComponentInfo(final DataInput input, final ConstantPool constantPool) throws IOException {
+ this.index = input.readUnsignedShort();
+ this.descriptorIndex = input.readUnsignedShort();
+ final int attributesCount = input.readUnsignedShort();
+ this.attributes = new Attribute[attributesCount];
+ for (int j = 0; j < attributesCount; j++) {
+ attributes[j] = Attribute.readAttribute(input, constantPool);
+ }
+ this.constantPool = constantPool;
+ }
+
+ @Override
+ public void accept(final Visitor v) {
+ v.visitRecordComponent(this);
+ }
+
+ /**
+ * Dumps contents into a file stream in binary format.
+ *
+ * @param file Output file stream
+ * @throws IOException if an I/O error occurs.
+ */
+ public void dump(final DataOutputStream file) throws IOException {
+ file.writeShort(index);
+ file.writeShort(descriptorIndex);
+ file.writeShort(attributes.length);
+ for (final Attribute attribute : attributes) {
+ attribute.dump(file);
+ }
+ }
+
+ /**
+ * Gets all attributes.
+ *
+ * @return all attributes.
+ */
+ public Attribute[] getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Gets the constant pool.
+ *
+ * @return Constant pool.
+ */
+ public ConstantPool getConstantPool() {
+ return constantPool;
+ }
+
+ /**
+ * Gets the description index.
+ *
+ * @return index in constant pool of this record component descriptor.
+ */
+ public int getDescriptorIndex() {
+ return descriptorIndex;
+ }
+
+ /**
+ * Gets the name index.
+ *
+ * @return index in constant pool of this record component name.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Converts this instance to a String suitable for debugging.
+ *
+ * @return a String suitable for debugging.
+ */
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ buf.append("RecordComponentInfo(");
+ buf.append(constantPool.getConstantString(index, Const.CONSTANT_Utf8));
+ buf.append(",");
+ buf.append(constantPool.getConstantString(descriptorIndex, Const.CONSTANT_Utf8));
+ buf.append(",");
+ buf.append(attributes.length);
+ buf.append("):\n");
+ for (final Attribute attribute : attributes) {
+ buf.append(" ").append(attribute.toString()).append("\n");
+ }
+ return buf.substring(0, buf.length() - 1); // remove the last newline
+ }
+
+}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
index 7afb8719559..7a7c539f15a 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java
@@ -28,13 +28,15 @@
import com.sun.org.apache.bcel.internal.Const;
/**
- * represents an annotation that is represented in the class file but is not provided to the JVM.
+ * An annotation that is represented in the class file but is not provided to the JVM.
*
* @since 6.0
*/
public class RuntimeInvisibleAnnotations extends Annotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
@@ -46,7 +48,9 @@ public RuntimeInvisibleAnnotations(final int nameIndex, final int length, final
}
/**
- * @return deep copy of this attribute
+ * Creates a deep copy of this attribute.
+ *
+ * @return deep copy of this attribute.
*/
@Override
public Attribute copy(final ConstantPool constantPool) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
index e4c3276f968..3d50ce16d40 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java
@@ -34,6 +34,8 @@
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
index c91c77387b9..4bf8e6f7197 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java
@@ -28,13 +28,15 @@
import com.sun.org.apache.bcel.internal.Const;
/**
- * represents an annotation that is represented in the class file and is provided to the JVM.
+ * An annotation that is represented in the class file and is provided to the JVM.
*
* @since 6.0
*/
public class RuntimeVisibleAnnotations extends Annotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
@@ -46,7 +48,9 @@ public RuntimeVisibleAnnotations(final int nameIndex, final int length, final Da
}
/**
- * @return deep copy of this attribute
+ * Creates a deep copy of this attribute.
+ *
+ * @return deep copy of this attribute.
*/
@Override
public Attribute copy(final ConstantPool constantPool) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
index 7e5d7eaaca3..ab5355235f6 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java
@@ -34,6 +34,8 @@
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
/**
+ * Constructs a new instance.
+ *
* @param nameIndex Index pointing to the name Code
* @param length Content length in bytes
* @param input Input stream
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
index 4f5d3a341b3..2161bbcb6ec 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java
@@ -110,7 +110,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
if ((ch = in.read()) == -1) {
throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF");
}
- // System.out.println("return from ident:" + (char)ch);
+ // System.out.println("return from ident:" + (char) ch);
if (!identStart(ch)) {
final StringBuilder buf2 = new StringBuilder();
int count = 1;
@@ -128,7 +128,7 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
buf.append(buf2);
ch = in.read();
in.unread();
- // System.out.println("so far:" + buf2 + ":next:" +(char)ch);
+ // System.out.println("so far:" + buf2 + ":next:" +(char) ch);
} else {
for (int i = 0; i < count; i++) {
in.unread();
@@ -141,10 +141,10 @@ private static void matchIdent(final MyByteArrayInputStream in, final StringBuil
do {
buf2.append((char) ch);
ch = in.read();
- // System.out.println("within ident:"+ (char)ch);
+ // System.out.println("within ident:"+ (char) ch);
} while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/'));
buf.append(Utility.pathToPackage(buf2.toString()));
- // System.out.println("regular return ident:"+ (char)ch + ":" + buf2);
+ // System.out.println("regular return ident:"+ (char) ch + ":" + buf2);
if (ch != -1) {
in.unread();
}
@@ -160,7 +160,7 @@ public static String translate(final String s) {
private int signatureIndex;
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
index 5e4e98d94df..e3e1cf40031 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java
@@ -54,7 +54,7 @@ public void dump(final DataOutputStream dos) throws IOException {
dos.writeShort(getIndex());
break;
default:
- throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type);
+ throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type);
}
}
@@ -67,7 +67,7 @@ public int getIndex() {
public boolean getValueBoolean() {
if (super.getType() != PRIMITIVE_BOOLEAN) {
- throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue");
+ throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue");
}
final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
return bo.getBytes() != 0;
@@ -75,21 +75,21 @@ public boolean getValueBoolean() {
public byte getValueByte() {
if (super.getType() != PRIMITIVE_BYTE) {
- throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue");
+ throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue");
}
return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public char getValueChar() {
if (super.getType() != PRIMITIVE_CHAR) {
- throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue");
+ throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue");
}
return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public double getValueDouble() {
if (super.getType() != PRIMITIVE_DOUBLE) {
- throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue");
+ throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue");
}
final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex());
return d.getBytes();
@@ -97,7 +97,7 @@ public double getValueDouble() {
public float getValueFloat() {
if (super.getType() != PRIMITIVE_FLOAT) {
- throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue");
+ throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue");
}
final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex());
return f.getBytes();
@@ -105,14 +105,14 @@ public float getValueFloat() {
public int getValueInt() {
if (super.getType() != PRIMITIVE_INT) {
- throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue");
+ throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue");
}
return super.getConstantPool().getConstantInteger(getIndex()).getBytes();
}
public long getValueLong() {
if (super.getType() != PRIMITIVE_LONG) {
- throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue");
+ throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue");
}
final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex());
return j.getBytes();
@@ -120,7 +120,7 @@ public long getValueLong() {
public short getValueShort() {
if (super.getType() != PRIMITIVE_SHORT) {
- throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue");
+ throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue");
}
final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex());
return (short) s.getBytes();
@@ -128,7 +128,7 @@ public short getValueShort() {
public String getValueString() {
if (super.getType() != STRING) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
index e9ceed21957..bfa9cbf8fcb 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java
@@ -40,7 +40,7 @@ public final class SourceFile extends Attribute {
private int sourceFileIndex;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
index 1f8ce5ea410..317638e6b2d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,8 +30,8 @@
/**
* This class represents a stack map attribute used for preverification of Java classes for the
- * Java 2 Micro Edition (J2ME). This attribute is used by the
- * KVM and contained within the Code attribute of a method. See CLDC
+ * Java 2 Micro Edition (J2ME). This attribute is used by the
+ * KVM and contained within the Code attribute of a method. See CLDC
* specification 5.3.1.2
*
*
@@ -46,14 +46,14 @@
* @see Code
* @see StackMapEntry
* @see StackMapType
- * @LastModified: Oct 2020
+ * @LastModified: Sept 2025
*/
public final class StackMap extends Attribute {
private StackMapEntry[] table; // Table of stack map entries
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index of name
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
index 110e30392ab..015083dd066 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
@@ -59,7 +59,7 @@ public final class StackMapEntry implements Node, Cloneable {
private ConstantPool constantPool;
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param dataInput Input stream
* @throws IOException if an I/O error occurs.
@@ -75,9 +75,7 @@ public final class StackMapEntry implements Node, Cloneable {
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
byteCodeOffset = dataInput.readUnsignedShort();
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
- } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
- byteCodeOffset = dataInput.readUnsignedShort();
- } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+ } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
byteCodeOffset = dataInput.readUnsignedShort();
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
byteCodeOffset = dataInput.readUnsignedShort();
@@ -167,7 +165,7 @@ public StackMapEntry copy() {
try {
e = (StackMapEntry) clone();
} catch (final CloneNotSupportedException ex) {
- throw new Error("Clone Not Supported");
+ throw new UnsupportedOperationException("Clone Not Supported", ex);
}
e.typesOfLocals = new StackMapType[typesOfLocals.length];
@@ -190,9 +188,7 @@ public void dump(final DataOutputStream file) throws IOException {
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
file.writeShort(byteCodeOffset);
typesOfStackItems[0].dump(file);
- } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
- file.writeShort(byteCodeOffset);
- } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+ } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
file.writeShort(byteCodeOffset);
} else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
file.writeShort(byteCodeOffset);
@@ -232,7 +228,6 @@ public int getFrameType() {
/**
* Calculate stack map entry size
- *
*/
int getMapEntrySize() {
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
index 4575b31dfce..b93066d53b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
@@ -34,9 +34,9 @@
* @see StackMap
* @see Const
*/
-public final class StackMapType implements Cloneable {
+public final class StackMapType implements Node, Cloneable {
- public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
+ public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY
private byte type;
private int index = -1; // Index to CONSTANT_Class or offset
@@ -53,7 +53,7 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
}
/**
- * Construct object from file stream.
+ * Constructs object from file stream.
*
* @param file Input stream
* @throws IOException if an I/O error occurs.
@@ -66,6 +66,18 @@ public StackMapType(final byte type, final int index, final ConstantPool constan
this.constantPool = constantPool;
}
+ /**
+ * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
+ * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
+ *
+ * @param v Visitor object
+ * @since 6.8.0
+ */
+ @Override
+ public void accept(final Visitor v) {
+ v.visitStackMapType(this);
+ }
+
private byte checkType(final byte type) {
if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
throw new ClassFormatException("Illegal type for StackMapType: " + type);
@@ -98,6 +110,15 @@ public void dump(final DataOutputStream file) throws IOException {
}
}
+ /**
+ * Gets the class name of this StackMapType from the constant pool at index position.
+ * @return the fully qualified name of the class for this StackMapType.
+ * @since 6.8.0
+ */
+ public String getClassName() {
+ return constantPool.constantToString(index, Const.CONSTANT_Class);
+ }
+
/**
* @return Constant pool used by this object.
*/
@@ -129,7 +150,7 @@ private String printIndex() {
if (index < 0) {
return ", class=";
}
- return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
+ return ", class=" + getClassName();
}
if (type == Const.ITEM_NewObject) {
return ", offset=" + index;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
index 3683fd6437e..c7fef8fcebc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
@@ -52,7 +52,7 @@ public Synthetic(final int nameIndex, final int length, final byte[] bytes, fina
}
/**
- * Construct object from input stream.
+ * Constructs object from input stream.
*
* @param nameIndex Index in constant pool to CONSTANT_Utf8
* @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
index 12dbbe4828a..6967dcefd94 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -43,7 +43,7 @@
/**
* Utility functions that do not really belong to any class in particular.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
// @since 6.0 methods are no longer final
public abstract class Utility {
@@ -51,7 +51,7 @@ public abstract class Utility {
/**
* Decode characters into bytes. Used by decode()
*/
- private static class JavaReader extends FilterReader {
+ private static final class JavaReader extends FilterReader {
public JavaReader(final Reader in) {
super(in);
@@ -88,10 +88,10 @@ public int read(final char[] cbuf, final int off, final int len) throws IOExcept
}
/**
- * Encode bytes into valid java identifier characters. Used by
+ * Encode bytes into valid Java identifier characters. Used by
* encode()
*/
- private static class JavaWriter extends FilterWriter {
+ private static final class JavaWriter extends FilterWriter {
public JavaWriter(final Writer out) {
super(out);
@@ -437,7 +437,9 @@ public static String codeToString(final ByteSequence bytes, final ConstantPool c
case Const.NEW:
case Const.CHECKCAST:
buf.append("\t");
- //$FALL-THROUGH$
+ index = bytes.readUnsignedShort();
+ buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
+ break;
case Const.INSTANCEOF:
index = bytes.readUnsignedShort();
buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
@@ -864,7 +866,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
vec.add(typeSignatureToString(signature.substring(index), chopit));
@@ -872,7 +874,7 @@ public static String[] methodSignatureArgumentTypes(final String signature, fina
index += unwrap(CONSUMER_CHARS); // update position
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return vec.toArray(Const.EMPTY_STRING_ARRAY);
}
@@ -903,11 +905,11 @@ public static String methodSignatureReturnType(final String signature, final boo
// Read return type after ')'
index = signature.lastIndexOf(')') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
type = typeSignatureToString(signature.substring(index), chopit);
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return type;
}
@@ -959,7 +961,7 @@ public static String methodSignatureToString(final String signature, final Strin
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
final String paramType = typeSignatureToString(signature.substring(index), chopit);
@@ -985,7 +987,7 @@ public static String methodSignatureToString(final String signature, final Strin
// Read return type after ')'
type = typeSignatureToString(signature.substring(index), chopit);
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
// ignore any throws information in the signature
if (buf.length() > 1) {
@@ -1172,7 +1174,7 @@ public static String signatureToString(final String signature, final boolean cho
type = typeParams + typeSignaturesToString(signature.substring(index), chopit, ')');
index += unwrap(CONSUMER_CHARS); // update position
// add return type
- type = type + typeSignatureToString(signature.substring(index), chopit);
+ type += typeSignatureToString(signature.substring(index), chopit);
index += unwrap(CONSUMER_CHARS); // update position
// ignore any throws information in the signature
return type;
@@ -1237,12 +1239,12 @@ public static byte typeOfMethodSignature(final String signature) throws ClassFor
int index;
try {
if (signature.charAt(0) != '(') {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
index = signature.lastIndexOf(')') + 1;
return typeOfSignature(signature.substring(index));
} catch (final StringIndexOutOfBoundsException e) {
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
@@ -1286,10 +1288,10 @@ public static byte typeOfSignature(final String signature) throws ClassFormatExc
case '*':
return typeOfSignature(signature.substring(1));
default:
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
} catch (final StringIndexOutOfBoundsException e) {
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
@@ -1469,8 +1471,8 @@ public static String typeSignatureToString(final String signature, final boolean
} else {
type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
// update our consumed count by the number of characters the for type argument
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
}
// are there more TypeArguments?
@@ -1490,8 +1492,8 @@ public static String typeSignatureToString(final String signature, final boolean
} else {
type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
// update our consumed count by the number of characters the for type argument
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
}
}
@@ -1508,14 +1510,14 @@ public static String typeSignatureToString(final String signature, final boolean
// update our consumed count by the number of characters the for type argument
// note that this count includes the "L" we added, but that is ok
// as it accounts for the "." we didn't consume
- consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, consumedChars);
+ consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, consumedChars);
return type.toString();
}
if (signature.charAt(consumedChars) != ';') {
throw new ClassFormatException("Invalid signature: " + signature);
}
- wrap(Utility.CONSUMER_CHARS, consumedChars + 1); // remove final ";"
+ wrap(CONSUMER_CHARS, consumedChars + 1); // remove final ";"
return type.toString();
}
case 'S':
@@ -1536,9 +1538,9 @@ public static String typeSignatureToString(final String signature, final boolean
// The rest of the string denotes a ''
type = typeSignatureToString(signature.substring(n), chopit);
// corrected concurrent private static field acess
- // Utility.consumed_chars += consumed_chars; is replaced by:
- final int temp = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
- wrap(Utility.CONSUMER_CHARS, temp);
+ // consumed_chars += consumed_chars; is replaced by:
+ final int temp = unwrap(CONSUMER_CHARS) + consumedChars;
+ wrap(CONSUMER_CHARS, temp);
return type + brackets.toString();
}
case 'V':
@@ -1552,11 +1554,11 @@ public static String typeSignatureToString(final String signature, final boolean
}
private static int unwrap(final ThreadLocal tl) {
- return tl.get();
+ return tl.get().intValue();
}
private static void wrap(final ThreadLocal tl, final int value) {
- tl.set(value);
+ tl.set(Integer.valueOf(value));
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
index 74cb8400d3e..1f6fe9c96ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
@@ -217,11 +217,32 @@ default void visitNestMembers(final NestMembers obj) {
*/
void visitParameterAnnotation(ParameterAnnotations obj);
+
/**
* @since 6.0
*/
void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
+ /**
+ * Visits a {@link Record} object.
+ *
+ * @param obj Record to visit
+ * @since 6.9.0
+ */
+ default void visitRecord(final Record obj) {
+ // empty
+ }
+
+ /**
+ * Visits a {@link RecordComponentInfo} object.
+ *
+ * @param record component to visit
+ * @since 6.9.0
+ */
+ default void visitRecordComponent(final RecordComponentInfo record) {
+ // noop
+ }
+
void visitSignature(Signature obj);
void visitSourceFile(SourceFile obj);
@@ -230,7 +251,18 @@ default void visitNestMembers(final NestMembers obj) {
void visitStackMapEntry(StackMapEntry obj);
+ /**
+ * Visits a {@link StackMapType} object.
+ *
+ * @param obj object to visit
+ * @since 6.8.0
+ */
+ default void visitStackMapType(final StackMapType obj) {
+ // empty
+ }
+
void visitSynthetic(Synthetic obj);
void visitUnknown(Unknown obj);
+
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
new file mode 100644
index 00000000000..4e8d383bcab
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Classes that describe the structure of a Java class file and a class file parser.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
index 2d7188e9174..db756700085 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,12 +28,12 @@
*
* Stack: ..., arrayref -> ..., length
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ {
/**
- * Get length of array
+ * Gets length of array
*/
public ARRAYLENGTH() {
super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
index bb2e953f850..07171fefde1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,8 +28,10 @@
*
* Stack: ..., objectref -> objectref
*
+ *
+ * @LastModified: Sept 2025
*/
-public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower {
+public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower, StackConsumer {
/**
* Throw exception
@@ -48,6 +50,7 @@ public ATHROW() {
public void accept(final Visitor v) {
v.visitUnconditionalBranch(this);
v.visitExceptionThrower(this);
+ v.visitStackConsumer(this);
v.visitATHROW(this);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
index ea01a837175..0fad6ea7389 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
import com.sun.org.apache.bcel.internal.classfile.Attribute;
@@ -37,10 +38,11 @@
import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleParameterAnnotations;
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations;
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations;
+import jdk.xml.internal.Utils;
/**
* @since 6.0
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public class AnnotationEntryGen {
@@ -53,7 +55,7 @@ public class AnnotationEntryGen {
* @param annotationEntryGens An array of AnnotationGen objects
*/
static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) {
- if (annotationEntryGens.length == 0) {
+ if (annotationEntryGens == null && annotationEntryGens.length == 0) {
return Attribute.EMPTY_ARRAY;
}
@@ -255,11 +257,7 @@ public void addElementNameValuePair(final ElementValuePairGen evp) {
}
private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
- final List out = new ArrayList<>();
- for (final ElementValuePair nvp : in) {
- out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries));
- }
- return out;
+ return Utils.streamOfIfNonNull(in).map(nvp -> new ElementValuePairGen(nvp, cpool, copyPoolEntries)).collect(Collectors.toList());
}
public void dump(final DataOutputStream dos) throws IOException {
@@ -286,18 +284,20 @@ public int getTypeIndex() {
}
public final String getTypeName() {
- return getTypeSignature();// BCELBUG: Should I use this instead?
+ return getTypeSignature(); // BCELBUG: Should I use this instead?
// Utility.signatureToString(getTypeSignature());
}
public final String getTypeSignature() {
- // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex);
+ // ConstantClass c = (ConstantClass) cpool.getConstant(typeIndex);
final ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex/* c.getNameIndex() */);
return utf8.getBytes();
}
/**
- * Returns list of ElementNameValuePair objects
+ * Returns list of ElementNameValuePair objects.
+ *
+ * @return list of ElementNameValuePair objects.
*/
public List getValues() {
return evs;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
index 71374877efe..59b774a9afc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,12 +24,15 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.classfile.ArrayElementValue;
import com.sun.org.apache.bcel.internal.classfile.ElementValue;
+import jdk.xml.internal.Utils;
/**
* @since 6.0
+ * @LastModified: Sept 2025
*/
public class ArrayElementValueGen extends ElementValueGen {
// J5TODO: Should we make this an array or a list? A list would be easier to
@@ -46,7 +48,7 @@ public ArrayElementValueGen(final ArrayElementValue value, final ConstantPoolGen
evalues = new ArrayList<>();
final ElementValue[] in = value.getElementValuesArray();
for (final ElementValue element : in) {
- evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries));
+ evalues.add(copy(element, cpool, copyPoolEntries));
}
}
@@ -55,15 +57,12 @@ public ArrayElementValueGen(final ConstantPoolGen cp) {
evalues = new ArrayList<>();
}
- public ArrayElementValueGen(final int type, final ElementValue[] datums, final ConstantPoolGen cpool) {
+ public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) {
super(type, cpool);
if (type != ARRAY) {
throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type);
}
- this.evalues = new ArrayList<>();
- for (final ElementValue datum : datums) {
- evalues.add(ElementValueGen.copy(datum, cpool, true));
- }
+ this.evalues = Utils.streamOfIfNonNull(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList());
}
public void addElement(final ElementValueGen gen) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
index 138999ebe90..78a676e875e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -24,6 +23,8 @@
/**
* Denotes array type, such as int[][]
+ *
+ * @LastModified: Sept 2025
*/
public final class ArrayType extends ReferenceType {
@@ -43,7 +44,7 @@ public ArrayType(final byte type, final int dimensions) {
/**
* Convenience constructor for reference array type, e.g. Object[]
*
- * @param className complete name of class (java.lang.String, e.g.)
+ * @param className complete name of class ({@link String}, for example)
* @param dimensions array dimensions
*/
public ArrayType(final String className, final int dimensions) {
@@ -56,6 +57,7 @@ public ArrayType(final String className, final int dimensions) {
* @param type type of array (may be an array itself)
* @param dimensions array dimensions
*/
+ @SuppressWarnings("deprecation") //signature
public ArrayType(final Type type, final int dimensions) {
super(Const.T_ARRAY, "");
if (dimensions < 1 || dimensions > Const.MAX_BYTE) {
@@ -79,7 +81,7 @@ public ArrayType(final Type type, final int dimensions) {
buf.append('[');
}
buf.append(basicType.getSignature());
- super.setSignature(buf.toString());
+ this.signature = buf.toString();
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
index 91ab9ac5463..f489f9a7658 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java
@@ -63,7 +63,7 @@ public InstructionHandle getTarget() {
}
/**
- * Set new contents. Old instruction is disposed and may not be used anymore.
+ * Sets new contents. Old instruction is disposed and may not be used anymore.
*/
@Override // This is only done in order to apply the additional type check; could be merged with super impl.
public void setInstruction(final Instruction i) { // TODO could be package-protected?
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
index 1dfd244141a..ff45e5cde93 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -35,7 +35,7 @@
* @see LDC
* @see INVOKEVIRTUAL
*
- * @LastModified: Jan 2020
+ * @LastModified: Sept 2025
*/
public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
@@ -104,7 +104,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the index to constant pool.
+ * Sets the index to constant pool.
*
* @param index in constant pool.
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
index 1c1c032dbd5..8e024eebaa4 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java
@@ -48,12 +48,12 @@ public ClassElementValueGen(final ClassElementValue value, final ConstantPoolGen
}
protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) {
- super(ElementValueGen.CLASS, cpool);
+ super(CLASS, cpool);
this.idx = typeIdx;
}
public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) {
- super(ElementValueGen.CLASS, cpool);
+ super(CLASS, cpool);
// this.idx = cpool.addClass(t);
idx = cpool.addUtf8(t.getSignature());
}
@@ -67,9 +67,9 @@ public void dump(final DataOutputStream dos) throws IOException {
public String getClassString() {
final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx);
return cu8.getBytes();
- // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx);
+ // ConstantClass c = (ConstantClass) getConstantPool().getConstant(idx);
// ConstantUtf8 utf8 =
- // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex());
+ // (ConstantUtf8) getConstantPool().getConstant(c.getNameIndex());
// return utf8.getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
index acaf4519567..debf930fe90 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,40 +40,37 @@
import com.sun.org.apache.bcel.internal.util.BCELComparator;
/**
- * Template class for building up a java class. May be initialized with an existing java class (file).
+ * Template class for building up a java class. May be initialized with an existing Java class (file).
*
* @see JavaClass
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ClassGen extends AccessFlags implements Cloneable {
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final ClassGen THIS = (ClassGen) o1;
- final ClassGen THAT = (ClassGen) o2;
- return Objects.equals(THIS.getClassName(), THAT.getClassName());
+ public boolean equals(final ClassGen a, final ClassGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName());
}
@Override
- public int hashCode(final Object o) {
- final ClassGen THIS = (ClassGen) o;
- return THIS.getClassName().hashCode();
+ public int hashCode(final ClassGen o) {
+ return o != null ? Objects.hashCode(o.getClassName()) : 0;
}
};
/**
* @return Comparison strategy object
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
* @param comparator Comparison strategy object
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -101,7 +98,7 @@ public static void setComparator(final BCELComparator comparator) {
private List observers;
/**
- * Initialize with existing class.
+ * Constructs a new instance from an existing class.
*
* @param clazz JavaClass object (e.g. read from file)
*/
@@ -118,15 +115,26 @@ public ClassGen(final JavaClass clazz) {
final Attribute[] attributes = clazz.getAttributes();
// J5TODO: Could make unpacking lazy, done on first reference
final AnnotationEntryGen[] annotations = unpackAnnotations(attributes);
- Collections.addAll(interfaceList, clazz.getInterfaceNames());
- for (final Attribute attribute : attributes) {
- if (!(attribute instanceof Annotations)) {
- addAttribute(attribute);
+ final String[] interfaceNames = clazz.getInterfaceNames();
+ if (interfaceNames != null) {
+ Collections.addAll(interfaceList, interfaceNames);
+ }
+ if (attributes != null) {
+ for (final Attribute attribute : attributes) {
+ if (!(attribute instanceof Annotations)) {
+ addAttribute(attribute);
+ }
}
}
Collections.addAll(annotationList, annotations);
- Collections.addAll(methodList, clazz.getMethods());
- Collections.addAll(fieldList, clazz.getFields());
+ final Method[] methods = clazz.getMethods();
+ if (methods != null) {
+ Collections.addAll(methodList, methods);
+ }
+ final Field[] fields = clazz.getFields();
+ if (fields != null) {
+ Collections.addAll(fieldList, fields);
+ }
}
/**
@@ -242,7 +250,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -282,7 +290,7 @@ public Method containsMethod(final String name, final String signature) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof ClassGen && bcelComparator.equals(this, (ClassGen) obj);
}
// J5TODO: Should we make calling unpackAnnotations() lazy and put it in here?
@@ -379,7 +387,7 @@ public int getSuperclassNameIndex() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name.
*
* @see Object#hashCode()
*/
@@ -478,7 +486,7 @@ public void setConstantPool(final ConstantPoolGen constantPool) {
}
/**
- * Set major version number of class file, default value is 45 (JDK 1.1)
+ * Sets major version number of class file, default value is 45 (JDK 1.1)
*
* @param major major version number
*/
@@ -492,11 +500,13 @@ public void setMethodAt(final Method method, final int pos) {
public void setMethods(final Method[] methods) {
methodList.clear();
- Collections.addAll(methodList, methods);
+ if (methods != null) {
+ Collections.addAll(methodList, methods);
+ }
}
/**
- * Set minor version number of class file, default value is 3 (JDK 1.1)
+ * Sets minor version number of class file, default value is 3 (JDK 1.1)
*
* @param minor minor version number
*/
@@ -515,17 +525,19 @@ public void setSuperclassNameIndex(final int superclassNameIndex) {
}
/**
- * Look for attributes representing annotations and unpack them.
+ * Unpacks attributes representing annotations.
*/
- private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) {
+ private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attributes) {
final List annotationGenObjs = new ArrayList<>();
- for (final Attribute attr : attrs) {
- if (attr instanceof RuntimeVisibleAnnotations) {
- final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
- rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
- } else if (attr instanceof RuntimeInvisibleAnnotations) {
- final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
- ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ if (attributes != null) {
+ for (final Attribute attr : attributes) {
+ if (attr instanceof RuntimeVisibleAnnotations) {
+ final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr;
+ rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ } else if (attr instanceof RuntimeInvisibleAnnotations) {
+ final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr;
+ ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false)));
+ }
}
}
return annotationGenObjs.toArray(AnnotationEntryGen.EMPTY_ARRAY);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
index fa660954d15..2518131ccee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java
@@ -63,7 +63,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -81,7 +81,7 @@ public ObjectType getCatchType() {
}
/**
- * Get CodeException object.
+ * Gets CodeException object.
*
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
* has been called for the instruction list.
@@ -120,7 +120,7 @@ public void setCatchType(final ObjectType catchType) {
}
/*
- * Set end of handler
+ * Sets end of handler
*
* @param endPc End of handled region (inclusive)
*/
@@ -130,7 +130,7 @@ public void setEndPC(final InstructionHandle endPc) { // TODO could be package-p
}
/*
- * Set handler code
+ * Sets handler code
*
* @param handlerPc Start of handler
*/
@@ -140,7 +140,7 @@ public void setHandlerPC(final InstructionHandle handlerPc) { // TODO could be p
}
/*
- * Set start of handler
+ * Sets start of handler
*
* @param startPc Start of handled region (inclusive)
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
index bdc9c517a86..878f392b6b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java
@@ -44,7 +44,7 @@ public ElementValuePairGen(final ElementValuePair nvp, final ConstantPoolGen cpo
// Could assert nvp.getNameString() points to the same thing as
// constantPoolGen.getConstant(nvp.getNameIndex())
// if
- // (!nvp.getNameString().equals(((ConstantUtf8)constantPoolGen.getConstant(nvp.getNameIndex())).getBytes()))
+ // (!nvp.getNameString().equals(((ConstantUtf8) constantPoolGen.getConstant(nvp.getNameIndex())).getBytes()))
// {
// throw new IllegalArgumentException("envp buggered");
// }
@@ -86,7 +86,7 @@ public int getNameIndex() {
}
public final String getNameString() {
- // ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx);
+ // ConstantString cu8 = (ConstantString) constantPoolGen.getConstant(nameIdx);
return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes();
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
index 95ac794f2d7..95c00ed3813 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java
@@ -40,10 +40,8 @@ public class EnumElementValueGen extends ElementValueGen {
public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
super(ENUM_CONSTANT, cpool);
if (copyPoolEntries) {
- typeIdx = cpool.addUtf8(value.getEnumTypeString());// was
- // addClass(value.getEnumTypeString());
- valueIdx = cpool.addUtf8(value.getEnumValueString()); // was
- // addString(value.getEnumValueString());
+ typeIdx = cpool.addUtf8(value.getEnumTypeString()); // was addClass(value.getEnumTypeString());
+ valueIdx = cpool.addUtf8(value.getEnumValueString()); // was addString(value.getEnumValueString());
} else {
typeIdx = value.getTypeIndex();
valueIdx = value.getValueIndex();
@@ -55,7 +53,7 @@ public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen c
* This ctor is used for deserialization
*/
protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) {
- super(ElementValueGen.ENUM_CONSTANT, cpool);
+ super(ENUM_CONSTANT, cpool);
if (super.getElementValueType() != ENUM_CONSTANT) {
throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType());
}
@@ -64,9 +62,9 @@ protected EnumElementValueGen(final int typeIdx, final int valueIdx, final Const
}
public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) {
- super(ElementValueGen.ENUM_CONSTANT, cpool);
- typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t);
- valueIdx = cpool.addUtf8(value);// was addString(value);
+ super(ENUM_CONSTANT, cpool);
+ typeIdx = cpool.addUtf8(t.getSignature()); // was addClass(t);
+ valueIdx = cpool.addUtf8(value); // was addString(value);
}
@Override
@@ -90,9 +88,9 @@ public ElementValue getElementValue() {
public String getEnumTypeString() {
// Constant cc = getConstantPool().getConstant(typeIdx);
// ConstantClass cu8 =
- // (ConstantClass)getConstantPool().getConstant(typeIdx);
+ // (ConstantClass) getConstantPool().getConstant(typeIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getNameIndex())).getBytes();
return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes();
// return Utility.signatureToString(cu8.getBytes());
}
@@ -100,9 +98,9 @@ public String getEnumTypeString() {
public String getEnumValueString() {
return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes();
// ConstantString cu8 =
- // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // (ConstantString) getConstantPool().getConstant(valueIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
public int getTypeIndex() {
@@ -118,8 +116,8 @@ public String stringifyValue() {
final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx);
return cu8.getBytes();
// ConstantString cu8 =
- // (ConstantString)getConstantPool().getConstant(valueIdx);
+ // (ConstantString) getConstantPool().getConstant(valueIdx);
// return
- // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
+ // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes();
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
index 86a0cad256c..2a488c85ede 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java
@@ -23,7 +23,7 @@
/**
* Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite
- * the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted.
+ * the truth as such; because all instructions may throw a {@link VirtualMachineError}. These exceptions are omitted.
*
* The Lava Language Specification specifies exactly which RUN-TIME and which LINKING exceptions each
* instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
index 9d1f4d41d93..30786370d29 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -40,37 +40,34 @@
* to a field (which must of course be compatible with to the declared type).
*
* @see Field
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class FieldGen extends FieldGenOrMethodGen {
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final FieldGen THIS = (FieldGen) o1;
- final FieldGen THAT = (FieldGen) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final FieldGen a, final FieldGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final FieldGen THIS = (FieldGen) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final FieldGen o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -81,8 +78,8 @@ public static void setComparator(final BCELComparator comparator) {
/**
* Instantiate from existing field.
*
- * @param field Field object
- * @param cp constant pool (must contain the same entries as the field's constant pool)
+ * @param field Field object.
+ * @param cp constant pool (must contain the same entries as the field's constant pool).
*/
public FieldGen(final Field field, final ConstantPoolGen cp) {
this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
@@ -187,11 +184,11 @@ public FieldGen copy(final ConstantPoolGen cp) {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof FieldGen && bcelComparator.equals(this, (FieldGen) obj);
}
/**
- * Get field object after having set up all necessary values.
+ * Gets field object after having set up all necessary values.
*/
public Field getField() {
final String signature = getSignature();
@@ -207,10 +204,7 @@ public Field getField() {
}
public String getInitValue() {
- if (value != null) {
- return value.toString();
- }
- return null;
+ return Objects.toString(value, null);
}
@Override
@@ -219,7 +213,7 @@ public String getSignature() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR
* signature.
*
* @see Object#hashCode()
@@ -295,7 +289,7 @@ public void setInitValue(final short s) {
}
/**
- * Set (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically.
+ * Sets (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically.
*/
public void setInitValue(final String str) {
checkType(ObjectType.getInstance("java.lang.String"));
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
index 6555392e9d4..bc1fbc8627e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,7 +30,7 @@
/**
* Super class for FieldGen and MethodGen objects, since they have some methods in common!
*
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
@@ -67,8 +67,10 @@ protected FieldGenOrMethodGen(final int accessFlags) { // TODO could this be pac
super(accessFlags);
}
- protected void addAll(final Attribute[] attrs) {
- Collections.addAll(attributeList, attrs);
+ protected void addAll(final Attribute[] attributes) {
+ if (attributes != null) {
+ Collections.addAll(attributeList, attributes);
+ }
}
/**
@@ -93,7 +95,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
index 1c646f48292..87ba4cb913e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java
@@ -53,7 +53,6 @@ protected FieldOrMethod(final short opcode, final int index) {
* generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an
* array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
* distinguishes between class types and array types.
- *
*/
@Deprecated
public String getClassName(final ConstantPoolGen cpg) {
@@ -89,6 +88,9 @@ public ObjectType getLoadClassType(final ConstantPoolGen cpg) {
if (rt instanceof ObjectType) {
return (ObjectType) rt;
}
+ if (rt instanceof ArrayType) {
+ return Type.OBJECT;
+ }
throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType");
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
index 5effd7edcd9..b3eb14a9ddf 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java
@@ -25,7 +25,6 @@
*
* Stack: ... -> ...,
*
- *
*/
public class ICONST extends Instruction implements ConstantPushInstruction {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
index 2865a158de2..998d072e067 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -37,7 +37,7 @@
* @see The
* invokedynamic instruction in The Java Virtual Machine Specification
* @since 6.0
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class INVOKEDYNAMIC extends InvokeInstruction {
@@ -104,11 +104,11 @@ public Class>[] getExceptions() {
}
/**
- * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, as that is the only type we can
+ * Since InvokeDynamic doesn't refer to a reference type, just return {@link Object}, as that is the only type we can
* say for sure the reference will be.
*
* @param cpg the ConstantPoolGen used to create the instruction
- * @return an ObjectType for java.lang.Object
+ * @return an ObjectType for {@link Object}
* @since 6.1
*/
@Override
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
index 16c8e2444b4..a7124409f12 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -29,7 +29,7 @@
/**
* Abstract super class for all Java byte codes.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public abstract class Instruction implements Cloneable {
@@ -461,7 +461,7 @@ public int consumeStack(final ConstantPoolGen cpg) {
public Instruction copy() {
Instruction i = null;
// "Constant" instruction, no need to duplicate
- if (InstructionConst.getInstruction(this.getOpcode()) != null) {
+ if (InstructionConst.getInstruction(getOpcode()) != null) {
i = this;
} else {
try {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
index 439268e35eb..7b95bfc99b1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java
@@ -170,7 +170,7 @@ public final class InstructionConst {
public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2);
/**
- * Get object via its opcode, for immutable instructions like branch instructions entries are set to null.
+ * Gets object via its opcode, for immutable instructions like branch instructions entries are set to null.
*/
static final Instruction[] INSTRUCTIONS = new Instruction[256];
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
index 5e9220354c3..3c4b3e9f9da 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,11 +30,11 @@
*
* @see Const
* @see InstructionConst
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class InstructionFactory {
- private static class MethodObject {
+ private static final class MethodObject {
final Type[] argTypes;
final Type resultType;
@@ -53,10 +53,12 @@ private static class MethodObject {
private static final String FQCN_STRING_BUFFER = "java.lang.StringBuffer";
- // N.N. These must agree with the order of Constants.T_CHAR through T_LONG
- private static final String[] shortNames = {"C", "F", "D", "B", "S", "I", "L"};
+ /**
+ * These must agree with the order of Constants.T_CHAR through T_LONG.
+ */
+ private static final String[] SHORT_NAMES = {"C", "F", "D", "B", "S", "I", "L"};
- private static final MethodObject[] appendMethodObjects = {
+ private static final MethodObject[] APPEND_METHOD_OBJECTS = {
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.STRING }),
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.OBJECT }), null, null, // indices 2, 3
new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }),
@@ -484,7 +486,7 @@ public InstructionFactory(final ConstantPoolGen cp) {
public Instruction createAppend(final Type type) {
final byte t = type.getType();
if (isString(type)) {
- return createInvoke(appendMethodObjects[0], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[0], Const.INVOKEVIRTUAL);
}
switch (t) {
case Const.T_BOOLEAN:
@@ -495,10 +497,10 @@ public Instruction createAppend(final Type type) {
case Const.T_SHORT:
case Const.T_INT:
case Const.T_LONG:
- return createInvoke(appendMethodObjects[t], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[t], Const.INVOKEVIRTUAL);
case Const.T_ARRAY:
case Const.T_OBJECT:
- return createInvoke(appendMethodObjects[1], Const.INVOKEVIRTUAL);
+ return createInvoke(APPEND_METHOD_OBJECTS[1], Const.INVOKEVIRTUAL);
default:
throw new IllegalArgumentException("No append for this type? " + type);
}
@@ -515,7 +517,7 @@ public Instruction createCast(final Type srcType, final Type destType) {
if (dest == Const.T_LONG && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) {
src = Const.T_INT;
}
- final String name = "com.sun.org.apache.bcel.internal.generic." + shortNames[src - Const.T_CHAR] + "2" + shortNames[dest - Const.T_CHAR];
+ final String name = "com.sun.org.apache.bcel.internal.generic." + SHORT_NAMES[src - Const.T_CHAR] + "2" + SHORT_NAMES[dest - Const.T_CHAR];
Instruction i = null;
try {
i = (Instruction) Class.forName(name).getDeclaredConstructor().newInstance();;
@@ -642,8 +644,10 @@ public InvokeInstruction createInvoke(final String className, final String name,
int index;
int nargs = 0;
final String signature = Type.getMethodSignature(retType, argTypes);
- for (final Type argType : argTypes) {
- nargs += argType.getSize();
+ if (argTypes != null) {
+ for (final Type argType : argTypes) {
+ nargs += argType.getSize();
+ }
}
if (useInterface) {
index = cp.addInterfaceMethodref(className, name, signature);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
index 5e962354d16..2c94b770265 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -38,7 +38,7 @@
* @see Instruction
* @see BranchHandle
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class InstructionHandle {
@@ -118,7 +118,7 @@ public void addTargeter(final InstructionTargeter t) {
if (targeters == null) {
targeters = new HashSet<>();
}
- // if(!targeters.contains(t))
+ // if (!targeters.contains(t))
targeters.add(t);
}
@@ -135,15 +135,12 @@ void dispose() {
}
/**
- * Get attribute of an instruction handle.
+ * Gets attribute of an instruction handle.
*
* @param key the key object to store/retrieve the attribute
*/
public Object getAttribute(final Object key) {
- if (attributes != null) {
- return attributes.get(key);
- }
- return null;
+ return attributes != null ? attributes.get(key) : null;
}
/**
@@ -247,7 +244,7 @@ final InstructionHandle setNext(final InstructionHandle next) {
}
/**
- * Set the position, i.e., the byte code offset of the contained instruction.
+ * Sets the position, i.e., the byte code offset of the contained instruction.
*/
void setPosition(final int pos) {
i_position = pos;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
index 7ffc3a8228e..579efc9fe3b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -33,6 +33,7 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.Constant;
import com.sun.org.apache.bcel.internal.util.ByteSequence;
+import jdk.xml.internal.Utils;
/**
* This class is a container for a list of Instruction objects. Instructions can be
@@ -46,7 +47,7 @@
* @see Instruction
* @see InstructionHandle
* @see BranchHandle
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class InstructionList implements Iterable {
@@ -60,23 +61,25 @@ public class InstructionList implements Iterable {
* @return target position's instruction handle if available
*/
public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) {
- int l = 0;
- int r = count - 1;
- /*
- * Do a binary search since the pos array is orderd.
- */
- do {
- final int i = l + r >>> 1;
- final int j = pos[i];
- if (j == target) {
- return ihs[i];
- }
- if (target < j) {
- r = i - 1;
- } else {
- l = i + 1;
- }
- } while (l <= r);
+ if (ihs != null && pos != null) {
+ int l = 0;
+ int r = count - 1;
+ /*
+ * Do a binary search since the pos array is orderd.
+ */
+ do {
+ final int i = l + r >>> 1;
+ final int j = pos[i];
+ if (j == target) {
+ return ihs[i];
+ }
+ if (target < j) {
+ r = i - 1;
+ } else {
+ l = i + 1;
+ }
+ } while (l <= r);
+ }
return null;
}
@@ -513,7 +516,7 @@ public void dispose() {
}
/**
- * Get instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly
+ * Gets instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly
* initialized from a byte array or setPositions() has been called before this method.
*
* @param pos byte code position to search for
@@ -605,7 +608,7 @@ public InstructionHandle[] getInstructionHandles() {
}
/**
- * Get positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from
+ * Gets positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from
* an byte code array, or that setPositions() has been called. Otherwise this may be inaccurate.
*
* @return array containing all instruction's offset in byte code
@@ -959,7 +962,7 @@ public void redirectBranches(final InstructionHandle oldTarget, final Instructio
* @see MethodGen
*/
public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
- for (final CodeExceptionGen exception : exceptions) {
+ Utils.streamOfIfNonNull(exceptions).forEach(exception -> {
if (exception.getStartPC() == oldTarget) {
exception.setStartPC(newTarget);
}
@@ -969,7 +972,7 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final
if (exception.getHandlerPC() == oldTarget) {
exception.setHandlerPC(newTarget);
}
- }
+ });
}
/**
@@ -981,16 +984,14 @@ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final
* @see MethodGen
*/
public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) {
- for (final LocalVariableGen element : lg) {
- final InstructionHandle start = element.getStart();
- final InstructionHandle end = element.getEnd();
- if (start == oldTarget) {
+ Utils.streamOfIfNonNull(lg).forEach(element -> {
+ if (element.getStart() == oldTarget) {
element.setStart(newTarget);
}
- if (end == oldTarget) {
+ if (element.getEnd() == oldTarget) {
element.setEnd(newTarget);
}
- }
+ });
}
/**
@@ -1120,7 +1121,7 @@ public void setPositions(final boolean check) { // called by code in other packa
ih.setPosition(index);
pos[count++] = index;
/*
- * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
+ * Gets an estimate about how many additional bytes may be added, because BranchInstructions may have variable length
* depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH).
*/
switch (i.getOpcode()) {
@@ -1132,11 +1133,14 @@ public void setPositions(final boolean check) { // called by code in other packa
case Const.LOOKUPSWITCH:
maxAdditionalBytes += 3;
break;
+ default:
+ // TODO should this be an error?
+ break;
}
index += i.getLength();
}
/*
- * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that
+ * Pass 2: Expand the variable-length (Branch) Instructions depending on the target offset (short or int) and ensure that
* branch targets are within this list.
*/
for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) {
@@ -1152,8 +1156,7 @@ public void setPositions(final boolean check) { // called by code in other packa
pos[count++] = index;
index += i.getLength();
}
- bytePositions = new int[count]; // Trim to proper size
- System.arraycopy(pos, 0, bytePositions, 0, count);
+ bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size
}
/**
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
index 5146408ef49..0681476b5ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java
@@ -22,7 +22,7 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Denote that a class targets InstructionHandles within an InstructionList. Namely the following implementers:
+ * Denotes that a class targets InstructionHandles within an InstructionList.
*
* @see BranchHandle
* @see LocalVariableGen
@@ -33,9 +33,12 @@ public interface InstructionTargeter {
// static final InstructionTargeter[] EMPTY_ARRAY = new InstructionTargeter[0];
/**
- * Checks whether this targeter targets the specified instruction handle.
+ * Tests whether this targeter targets the specified instruction handle.
+ *
+ * @param instructionHandle the instruction handle to test.
+ * @return whether this targeter targets the specified instruction handle.
*/
- boolean containsTarget(InstructionHandle ih);
+ boolean containsTarget(InstructionHandle instructionHandle);
/**
* Replaces the target of this targeter from this old handle to the new handle.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
index c517b492f0a..188ac95f6ef 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java
@@ -27,7 +27,6 @@
*
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
*
- *
*/
public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
index d95bade23bd..13ca0a84cfa 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java
@@ -94,6 +94,8 @@ public Type getType(final ConstantPoolGen cpg) {
return Type.INT;
case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class:
return Type.CLASS;
+ case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic:
+ return Type.OBJECT;
default: // Never reached
throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
}
@@ -113,7 +115,10 @@ public Object getValue(final ConstantPoolGen cpg) {
case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class:
final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex();
c = cpg.getConstantPool().getConstant(nameIndex);
- return Type.getType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes());
+ return Type.getType(Type.internalTypeNameToSignature(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()));
+ case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic:
+ // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it?
+ return c;
default: // Never reached
throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex());
}
@@ -129,7 +134,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the index to constant pool and adjust size.
+ * Sets the index to constant pool and adjust size.
*/
@Override
public final void setIndex(final int index) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
index 3773c21e7b3..68bb2abf513 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java
@@ -54,7 +54,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
@@ -71,7 +71,7 @@ public InstructionHandle getInstruction() {
}
/**
- * Get LineNumber attribute.
+ * Gets LineNumber attribute.
*
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
* has been called for the instruction list.
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
index 830564d42c9..71cfa0cf1c2 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java
@@ -85,7 +85,7 @@ public Object clone() {
try {
return super.clone();
} catch (final CloneNotSupportedException e) {
- throw new Error("Clone Not Supported"); // never happens
+ throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
index 67184c0b9f1..f952a65880b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,7 +28,7 @@
/**
* Abstract super class for instructions dealing with local variables.
*
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
@@ -162,7 +162,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set the local variable index. also updates opcode and length TODO Why?
+ * Sets the local variable index. also updates opcode and length TODO Why?
*
* @see #setIndexOnly(int)
*/
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
index f6e8333be79..be09b0a5159 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -27,6 +27,7 @@
import java.util.List;
import java.util.Objects;
import java.util.Stack;
+import java.util.stream.Collectors;
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry;
@@ -46,6 +47,7 @@
import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import com.sun.org.apache.bcel.internal.util.BCELComparator;
+import jdk.xml.internal.Utils;
/**
* Template class for building up a method. This is done by defining exception handlers, adding thrown exceptions, local
@@ -57,7 +59,7 @@
*
* @see InstructionList
* @see Method
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class MethodGen extends FieldGenOrMethodGen {
@@ -102,19 +104,16 @@ static final class BranchTarget {
}
}
- private static BCELComparator bcelComparator = new BCELComparator() {
+ private static BCELComparator bcelComparator = new BCELComparator() {
@Override
- public boolean equals(final Object o1, final Object o2) {
- final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o1;
- final FieldGenOrMethodGen THAT = (FieldGenOrMethodGen) o2;
- return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature());
+ public boolean equals(final FieldGenOrMethodGen a, final FieldGenOrMethodGen b) {
+ return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature());
}
@Override
- public int hashCode(final Object o) {
- final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o;
- return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
+ public int hashCode(final FieldGenOrMethodGen o) {
+ return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0;
}
};
@@ -127,9 +126,9 @@ private static byte[] getByteCodes(final Method method) {
}
/**
- * @return Comparison strategy object
+ * @return Comparison strategy object.
*/
- public static BCELComparator getComparator() {
+ public static BCELComparator getComparator() {
return bcelComparator;
}
@@ -206,9 +205,9 @@ public static int getMaxStack(final ConstantPoolGen cp, final InstructionList il
}
/**
- * @param comparator Comparison strategy object
+ * @param comparator Comparison strategy object.
*/
- public static void setComparator(final BCELComparator comparator) {
+ public static void setComparator(final BCELComparator comparator) {
bcelComparator = comparator;
}
@@ -636,7 +635,7 @@ private void ensureExistingParameterAnnotationsUnpacked() {
*/
@Override
public boolean equals(final Object obj) {
- return bcelComparator.equals(this, obj);
+ return obj instanceof FieldGenOrMethodGen && bcelComparator.equals(this, (FieldGenOrMethodGen) obj);
}
// J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this
@@ -790,7 +789,7 @@ public int getMaxStack() {
}
/**
- * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method
+ * Gets method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method
* (the same applies for max locals).
*
* @return method object
@@ -888,7 +887,7 @@ public String getSignature() {
}
/**
- * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR
+ * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR
* signature.
*
* @see Object#hashCode()
@@ -899,11 +898,7 @@ public int hashCode() {
}
private List makeMutableVersion(final AnnotationEntry[] mutableArray) {
- final List result = new ArrayList<>();
- for (final AnnotationEntry element : mutableArray) {
- result.add(new AnnotationEntryGen(element, getConstantPool(), false));
- }
- return result;
+ return Utils.streamOfIfNonNull(mutableArray).map(ae -> new AnnotationEntryGen(ae, getConstantPool(), false)).collect(Collectors.toList());
}
/**
@@ -1027,10 +1022,8 @@ public void removeObserver(final MethodObserver o) {
*
* @since 6.5.0
*/
- public void removeRuntimeAttributes(final Attribute[] attrs) {
- for (final Attribute attr : attrs) {
- removeAttribute(attr);
- }
+ public void removeRuntimeAttributes(final Attribute[] attributes) {
+ Utils.streamOfIfNonNull(attributes).forEach(this::removeAttribute);
}
public void setArgumentName(final int i, final String name) {
@@ -1038,7 +1031,7 @@ public void setArgumentName(final int i, final String name) {
}
public void setArgumentNames(final String[] argNames) {
- this.argNames = argNames;
+ this.argNames = Utils.createEmptyArrayIfNull(argNames, String[].class);
}
public void setArgumentType(final int i, final Type type) {
@@ -1046,7 +1039,7 @@ public void setArgumentType(final int i, final Type type) {
}
public void setArgumentTypes(final Type[] argTypes) {
- this.argTypes = argTypes;
+ this.argTypes = argTypes != null ? argTypes : Type.NO_ARGS;
}
public void setClassName(final String className) { // TODO could be package-protected?
@@ -1084,7 +1077,7 @@ public void setMaxLocals() { // TODO could be package-protected? (some tests wou
}
/**
- * Set maximum number of local variables.
+ * Sets maximum number of local variables.
*/
public void setMaxLocals(final int m) {
maxLocals = m;
@@ -1102,7 +1095,7 @@ public void setMaxStack() { // TODO could be package-protected? (some tests woul
}
/**
- * Set maximum stack size for this method.
+ * Sets maximum stack size for this method.
*/
public void setMaxStack(final int m) { // TODO could be package-protected?
maxStack = m;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
index 46378a1b71e..622a3cdd961 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java
@@ -27,7 +27,7 @@
import com.sun.org.apache.bcel.internal.classfile.Utility;
/**
- * Denotes reference such as java.lang.String.
+ * Denotes reference such as {@link String}.
*/
public class ObjectType extends ReferenceType {
@@ -47,7 +47,7 @@ public static ObjectType getInstance(final String className) {
/**
* Constructs a new instance.
*
- * @param className fully qualified class name, e.g. java.lang.String
+ * @param className fully qualified class name, e.g. {@link String}
*/
public ObjectType(final String className) {
super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";");
@@ -151,7 +151,7 @@ public boolean referencesInterfaceExact() throws ClassNotFoundException {
* @throws ClassNotFoundException if any of this class's superclasses can't be found
*/
public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException {
- if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
+ if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) {
return false;
}
return Repository.instanceOf(this.className, superclass.className);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
index a7cacc7c165..99a1efbed16 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java
@@ -110,7 +110,7 @@ protected void initFromFile(final ByteSequence bytes, final boolean wide) throws
}
/**
- * Set index of local variable containg the return address
+ * Sets index of local variable containg the return address
*/
@Override
public final void setIndex(final int n) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
index fe75792e213..9b94a1dcf2d 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java
@@ -42,10 +42,10 @@ protected ReferenceType(final byte t, final String s) {
/**
* This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an
- * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t
- * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
- * "this" or t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an
- * interface, then Type.OBJECT is returned. If not all of the two classes' superclasses cannot be found, "null" is
+ * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t
+ * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
+ * "this" or t is an ArrayType, then {@link #OBJECT} is returned. If "this" or t is a ReferenceType referencing an
+ * interface, then {@link #OBJECT} is returned. If not all of the two classes' superclasses cannot be found, "null" is
* returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier".
*
* @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics.
@@ -53,46 +53,46 @@ protected ReferenceType(final byte t, final String s) {
*/
@Deprecated
public ReferenceType firstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t;
}
- if (t.equals(Type.NULL) || this.equals(t)) {
+ if (t.equals(NULL) || equals(t)) {
return this;
/*
- * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also
- * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's
- * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :)
+ * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also
+ * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's
+ * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :)
*/
}
if (this instanceof ArrayType || t instanceof ArrayType) {
- return Type.OBJECT;
- // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ return OBJECT;
+ // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType?
}
return getFirstCommonSuperclassInternal(t);
}
/**
* This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an
- * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t
- * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
- * "this" or t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the
+ * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t
+ * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If
+ * "this" or t is an ArrayType, then {@link #OBJECT} is returned; unless their dimensions match. Then an ArrayType of the
* same number of dimensions is returned, with its basic type being the first common super class of the basic types of
- * "this" and t. If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of
+ * "this" and t. If "this" or t is a ReferenceType referencing an interface, then {@link #OBJECT} is returned. If not all of
* the two classes' superclasses cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The
* Bytecode Verifier".
*
* @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter
*/
public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t;
}
- if (t.equals(Type.NULL) || this.equals(t)) {
+ if (t.equals(NULL) || equals(t)) {
return this;
/*
- * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also
- * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's
- * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :)
+ * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also
+ * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's
+ * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :)
*/
}
/* This code is from a bug report by Konstantin Shagin */
@@ -106,8 +106,8 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas
}
}
if (this instanceof ArrayType || t instanceof ArrayType) {
- return Type.OBJECT;
- // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType?
+ return OBJECT;
+ // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType?
}
return getFirstCommonSuperclassInternal(t);
}
@@ -115,7 +115,7 @@ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws Clas
private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) throws ClassNotFoundException {
if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact()
|| t instanceof ObjectType && ((ObjectType) t).referencesInterfaceExact()) {
- return Type.OBJECT;
+ return OBJECT;
// TODO: The above line is correct comparing to the vmspec2. But one could
// make class file verification a bit stronger here by using the notion of
// superinterfaces or even castability or assignment compatibility.
@@ -142,7 +142,7 @@ private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) th
}
}
}
- // Huh? Did you ask for Type.OBJECT's superclass??
+ // Huh? Did you ask for OBJECT's superclass??
return null;
}
@@ -158,7 +158,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
return false;
}
final ReferenceType T = (ReferenceType) t;
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return true; // This is not explicitly stated, but clear. Isn't it?
}
/*
@@ -169,7 +169,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
* If T is a class type, then this must be the same class as T, or this must be a subclass of T;
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact()
- && (this.equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
+ && (equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
return true;
}
/*
@@ -187,14 +187,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/*
* If T is a class type, then T must be Object (2.4.7).
*/
- if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) {
+ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
return true;
}
/*
* If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2).
*/
if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact()
- && (this.equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
+ && (equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) {
return true;
}
}
@@ -205,7 +205,7 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/*
* If T is a class type, then T must be Object (2.4.7).
*/
- if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) {
+ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) {
return true;
}
/*
@@ -246,14 +246,14 @@ public boolean isAssignmentCompatibleWith(final Type t) throws ClassNotFoundExce
/**
* Return true iff this type is castable to another type t as defined in the JVM specification. The case where this is
- * Type.NULL is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST
+ * {@link #NULL} is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST
* doesn't throw a ClassCastException when casting a null reference to any Object, true is returned in this case.
*
* @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be
* found
*/
public boolean isCastableTo(final Type t) throws ClassNotFoundException {
- if (this.equals(Type.NULL)) {
+ if (equals(NULL)) {
return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible()
}
return isAssignmentCompatibleWith(t);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
index aed1626ec0d..f929176c174 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java
@@ -95,7 +95,7 @@ public SWITCH(final int[] match, final InstructionHandle[] targets, final Instru
* @param maxGap maximum gap that may between case branches
*/
public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int maxGap) {
- int[] matchClone = match.clone();
+ final int[] matchClone = match.clone();
final InstructionHandle[] targetsClone = targets.clone();
final int matchLength = match.length;
if (matchLength < 2) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
index a90e795e99f..a3086ac1664 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -33,7 +33,7 @@
* @see LOOKUPSWITCH
* @see TABLESWITCH
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class Select extends BranchInstruction implements VariableLengthInstruction, StackConsumer /* @since 6.0 */, StackProducer {
@@ -87,7 +87,7 @@ public abstract class Select extends BranchInstruction implements VariableLength
* @param defaultTarget default instruction target
*/
Select(final short opcode, final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) {
- // don't set default target before instuction is built
+ // don't set default target before instruction is built
super(opcode, null);
this.match = match;
this.targets = targets;
@@ -288,7 +288,7 @@ final int setMatchLength(final int matchLength) {
}
/**
- * Set branch target for 'i'th case
+ * Sets branch target for 'i'th case
*/
public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected?
notifyTarget(targets[i], target, this);
@@ -314,7 +314,11 @@ public String toString(final boolean verbose) {
for (int i = 0; i < match_length; i++) {
String s = "null";
if (targets[i] != null) {
- s = targets[i].getInstruction().toString();
+ if (targets[i].getInstruction() == this) {
+ s = "";
+ } else {
+ s = targets[i].getInstruction().toString();
+ }
}
buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(indices[i]).append("})");
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
index a4de20315d7..363b3237632 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java
@@ -166,7 +166,7 @@ public void dump(final DataOutputStream dos) throws IOException {
dos.writeShort(idx);
break;
default:
- throw new IllegalStateException("SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType());
+ throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType());
}
}
@@ -184,7 +184,7 @@ public int getIndex() {
public int getValueInt() {
if (super.getElementValueType() != PRIMITIVE_INT) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx);
return c.getBytes();
@@ -192,7 +192,7 @@ public int getValueInt() {
public String getValueString() {
if (super.getElementValueType() != STRING) {
- throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue");
+ throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue");
}
final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx);
return c.getBytes();
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
index 30310356f21..4ce125cdabc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -21,44 +21,46 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Thrown by InstructionList.remove() when one or multiple disposed instructions are still being referenced by an
- * InstructionTargeter object. I.e. the InstructionTargeter has to be notified that (one of) the InstructionHandle it is
- * referencing is being removed from the InstructionList and thus not valid anymore.
+ * Thrown by {@link InstructionList} when one or multiple disposed instructions are still being referenced by an {@link InstructionTargeter} object. I.e. the
+ * {@link InstructionTargeter} has to be notified that (one of) the {@link InstructionHandle} it is referencing is being removed from the
+ * {@link InstructionList} and thus not valid anymore.
*
*
- * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... }
- * catch. The following code illustrates how this may be done:
+ * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } catch. The following code illustrates how
+ * this may be done:
*
*
- *
+ *
* ...
* try {
* il.delete(start_ih, end_ih);
- * } catch(TargetLostException e) {
+ * } catch (TargetLostException e) {
* for (InstructionHandle target : e.getTargets()) {
* for (InstructionTargeter targeter : target.getTargeters()) {
* targeter.updateTarget(target, new_target);
* }
* }
* }
- *
+ *
*
* @see InstructionHandle
* @see InstructionList
* @see InstructionTargeter
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public final class TargetLostException extends Exception {
private static final long serialVersionUID = -6857272667645328384L;
private final InstructionHandle[] targets;
- TargetLostException(final InstructionHandle[] t, final String mesg) {
- super(mesg);
- targets = t;
+ TargetLostException(final InstructionHandle[] targets, final String message) {
+ super(message);
+ this.targets = targets;
}
/**
+ * Gets the list of instructions still being targeted.
+ *
* @return list of instructions still being targeted.
*/
public InstructionHandle[] getTargets() {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
index ea20710af2e..b58645b402e 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -26,12 +26,14 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.classfile.ClassFormatException;
+import com.sun.org.apache.bcel.internal.classfile.InvalidMethodSignatureException;
import com.sun.org.apache.bcel.internal.classfile.Utility;
+import jdk.xml.internal.Utils;
/**
- * Abstract super class for all possible java types, namely basic types such as int, object types like String and array
+ * Abstract super class for all possible Java types, namely basic types such as int, object types like String and array
* types, e.g. int[]
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public abstract class Type {
@@ -88,15 +90,15 @@ public static Type[] getArgumentTypes(final String signature) {
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
vec.add(getType(signature.substring(index)));
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
index += unwrap(CONSUMED_CHARS); // update position
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
final Type[] types = new Type[vec.size()];
vec.toArray(types);
@@ -110,7 +112,7 @@ static int getArgumentTypesSize(final String signature) {
// Skip any type arguments to read argument declarations between '(' and ')'
index = signature.indexOf('(') + 1;
if (index <= 0) {
- throw new ClassFormatException("Invalid method signature: " + signature);
+ throw new InvalidMethodSignatureException(signature);
}
while (signature.charAt(index) != ')') {
final int coded = getTypeSize(signature.substring(index));
@@ -118,7 +120,7 @@ static int getArgumentTypesSize(final String signature) {
index += consumed(coded);
}
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
return res;
}
@@ -154,13 +156,13 @@ public static Type getReturnType(final String signature) {
final int index = signature.lastIndexOf(')') + 1;
return getType(signature.substring(index));
} catch (final StringIndexOutOfBoundsException e) { // Should never occur
- throw new ClassFormatException("Invalid method signature: " + signature, e);
+ throw new InvalidMethodSignatureException(signature, e);
}
}
static int getReturnTypeSize(final String signature) {
final int index = signature.lastIndexOf(')') + 1;
- return Type.size(getTypeSize(signature.substring(index)));
+ return size(getTypeSize(signature.substring(index)));
}
public static String getSignature(final java.lang.reflect.Method meth) {
@@ -175,7 +177,7 @@ public static String getSignature(final java.lang.reflect.Method meth) {
}
/**
- * Convert runtime java.lang.Class to BCEL Type object.
+ * Convert runtime {@link Class} to BCEL Type object.
*
* @param cls Java class
* @return corresponding Type object
@@ -183,7 +185,7 @@ public static String getSignature(final java.lang.reflect.Method meth) {
public static Type getType(final Class> cls) {
Objects.requireNonNull(cls, "cls");
/*
- * That's an amzingly easy case, because getName() returns the signature. That's what we would have liked anyway.
+ * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway.
*/
if (cls.isArray()) {
return getType(cls.getName());
@@ -230,7 +232,7 @@ public static Type getType(final Class> cls) {
public static Type getType(final String signature) throws StringIndexOutOfBoundsException {
final byte type = Utility.typeOfSignature(signature);
if (type <= Const.T_VOID) {
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
wrap(CONSUMED_CHARS, 1);
return BasicType.getType(type);
}
@@ -246,7 +248,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds
} while (signature.charAt(dim) == '[');
// Recurse, but just once, if the signature is ok
final Type t = getType(signature.substring(dim));
- // corrected concurrent private static field acess
+ // corrected concurrent private static field access
// consumed_chars += dim; // update counter - is replaced by
final int temp = unwrap(CONSUMED_CHARS) + dim;
wrap(CONSUMED_CHARS, temp);
@@ -254,7 +256,7 @@ public static Type getType(final String signature) throws StringIndexOutOfBounds
}
/**
- * Convert runtime java.lang.Class[] to BCEL Type objects.
+ * Convert runtime {@code java.lang.Class[]} to BCEL Type objects.
*
* @param classes an array of runtime class objects
* @return array of corresponding Type objects
@@ -286,6 +288,24 @@ static int getTypeSize(final String signature) throws StringIndexOutOfBoundsExce
return encode(1, index + 1);
}
+ static String internalTypeNameToSignature(final String internalTypeName) {
+ if (Utils.isEmpty(internalTypeName) || Arrays.asList(Const.SHORT_TYPE_NAMES).contains(internalTypeName)) {
+ return internalTypeName;
+ }
+ switch (internalTypeName.charAt(0)) {
+ case '[':
+ return internalTypeName;
+ case 'L':
+ case 'T':
+ if (internalTypeName.charAt(internalTypeName.length() - 1) == ';') {
+ return internalTypeName;
+ }
+ return 'L' + internalTypeName + ';';
+ default:
+ return 'L' + internalTypeName + ';';
+ }
+ }
+
static int size(final int coded) {
return coded & 3;
}
@@ -361,7 +381,7 @@ public byte getType() {
}
/**
- * @return hashcode of Type
+ * @return hash code of Type
*/
@Override
public int hashCode() {
@@ -369,31 +389,23 @@ public int hashCode() {
}
/**
- * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link Type#INT}
- * for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise returns the given type.
+ * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link #INT}
+ * for {@link #BOOLEAN}, {@link #SHORT} or {@link #CHAR}, otherwise returns the given type.
*
* @since 6.0
*/
public Type normalizeForStackOrLocal() {
- if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) {
- return Type.INT;
+ if (this == BOOLEAN || this == BYTE || this == SHORT || this == CHAR) {
+ return INT;
}
return this;
}
- /*
- * Currently only used by the ArrayType constructor. The signature has a complicated dependency on other parameter so
- * it's tricky to do it in a call to the super ctor.
- */
- void setSignature(final String signature) {
- this.signature = signature;
- }
-
/**
* @return Type string, e.g. 'int[]'
*/
@Override
public String toString() {
- return this.equals(Type.NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false);
+ return equals(NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false);
}
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
index 5a22942a6a7..27b952f3996 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java
@@ -22,7 +22,7 @@
package com.sun.org.apache.bcel.internal.generic;
/**
- * Get the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g..
+ * Gets the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g..
*/
public interface TypedInstruction {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java
new file mode 100644
index 00000000000..63d4dc876ce
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Generic part of the Apache Byte Code Engineering Library (BCEL), classes to dynamically modify class objects
+ * and byte code instructions.
+ */
+package com.sun.org.apache.bcel.internal.generic;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java
new file mode 100644
index 00000000000..581037d7981
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Basic classes for the Apache Byte Code Engineering Library (BCEL) and constants defined by the
+ * JVM specification.
+ */
+package com.sun.org.apache.bcel.internal;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
index 2e663bfdaa1..fb32dc35e0b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java
@@ -22,26 +22,27 @@
package com.sun.org.apache.bcel.internal.util;
/**
- * Used for BCEL comparison strategy
+ * Used for BCEL comparison strategy.
*
+ * @param What type we are comparing.
* @since 5.2
*/
-public interface BCELComparator {
+public interface BCELComparator {
/**
- * Compare two objects and return what THIS.equals(THAT) should return
+ * Compares two objects and return what a.equals(b) should return.
*
- * @param THIS
- * @param THAT
- * @return true if and only if THIS equals THAT
+ * @param a an object.
+ * @param b an object to be compared with {@code a} for equality.
+ * @return {@code true} if the arguments are equal to each other and {@code false} otherwise.
*/
- boolean equals(Object THIS, Object THAT);
+ boolean equals(T a, T b);
/**
- * Return hashcode for THIS.hashCode()
+ * Gets the hash code for o.hashCode()
*
- * @param THIS
- * @return hashcode for THIS.hashCode()
+ * @param o
+ * @return hash code for o.hashCode()
*/
- int hashCode(Object THIS);
+ int hashCode(T o);
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
index c931fb1e422..93f22e7d0ad 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -63,9 +63,9 @@
* Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier.
*
* @see BCELifier
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
-class BCELFactory extends EmptyVisitor {
+final class BCELFactory extends EmptyVisitor {
private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + ".";
private final MethodGen methodGen;
@@ -88,7 +88,7 @@ private void createConstant(final Object value) {
if (value instanceof String) {
embed = '"' + Utility.convertString(embed) + '"';
} else if (value instanceof Character) {
- embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
+ embed = "(char) 0x" + Integer.toHexString(((Character) value).charValue());
} else if (value instanceof Float) {
final Float f = (Float) value;
if (Float.isNaN(f)) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
index 151083ea71b..0eb9bfb4ee1 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,11 +30,15 @@
import com.sun.org.apache.bcel.internal.Const;
import com.sun.org.apache.bcel.internal.Repository;
import com.sun.org.apache.bcel.internal.classfile.ClassParser;
+import com.sun.org.apache.bcel.internal.classfile.Code;
import com.sun.org.apache.bcel.internal.classfile.ConstantValue;
import com.sun.org.apache.bcel.internal.classfile.ExceptionTable;
import com.sun.org.apache.bcel.internal.classfile.Field;
import com.sun.org.apache.bcel.internal.classfile.JavaClass;
import com.sun.org.apache.bcel.internal.classfile.Method;
+import com.sun.org.apache.bcel.internal.classfile.StackMap;
+import com.sun.org.apache.bcel.internal.classfile.StackMapEntry;
+import com.sun.org.apache.bcel.internal.classfile.StackMapType;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import com.sun.org.apache.bcel.internal.generic.ArrayType;
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
@@ -46,7 +50,7 @@
* This gives new users of BCEL a useful example showing how things are done with BCEL. It does not cover all features
* of BCEL, but tries to mimic hand-written code as close as possible.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor {
@@ -74,7 +78,7 @@ static JavaClass getJavaClass(final String name) throws ClassNotFoundException,
/**
* Default main method
*/
- public static void _main(final String[] argv) throws Exception {
+ public static void main(final String[] argv) throws Exception {
if (argv.length != 1) {
System.out.println("Usage: BCELifier className");
System.out.println("\tThe class must exist on the classpath");
@@ -311,6 +315,13 @@ public void visitMethod(final Method method) {
printWriter.println("\");");
}
}
+ final Code code = method.getCode();
+ if (code != null) {
+ final StackMap stackMap = code.getStackMap();
+ if (stackMap != null) {
+ stackMap.accept(this);
+ }
+ }
printWriter.println();
final BCELFactory factory = new BCELFactory(mg, printWriter);
factory.start();
@@ -319,4 +330,78 @@ public void visitMethod(final Method method) {
printWriter.println(" _cg.addMethod(method.getMethod());");
printWriter.println(" il.dispose();");
}
+
+ @Override
+ public void visitStackMap(final StackMap stackMap) {
+ super.visitStackMap(stackMap);
+ printWriter.print(" method.addCodeAttribute(");
+ printWriter.print("new StackMap(_cp.addUtf8(\"");
+ printWriter.print(stackMap.getName());
+ printWriter.print("\"), ");
+ printWriter.print(stackMap.getLength());
+ printWriter.print(", ");
+ printWriter.print("new StackMapEntry[] {");
+ final StackMapEntry[] table = stackMap.getStackMap();
+ for (int i = 0; i < table.length; i++) {
+ table[i].accept(this);
+ if (i < table.length - 1) {
+ printWriter.print(", ");
+ } else {
+ printWriter.print(" }");
+ }
+ }
+ printWriter.print(", _cp.getConstantPool())");
+ printWriter.println(");");
+ }
+
+ @Override
+ public void visitStackMapEntry(final StackMapEntry stackMapEntry) {
+ super.visitStackMapEntry(stackMapEntry);
+ printWriter.print("new StackMapEntry(");
+ printWriter.print(stackMapEntry.getFrameType());
+ printWriter.print(", ");
+ printWriter.print(stackMapEntry.getByteCodeOffset());
+ printWriter.print(", ");
+ visitStackMapTypeArray(stackMapEntry.getTypesOfLocals());
+ printWriter.print(", ");
+ visitStackMapTypeArray(stackMapEntry.getTypesOfStackItems());
+ printWriter.print(", _cp.getConstantPool())");
+ }
+
+ /**
+ * Visits a {@link StackMapType} object.
+ * @param stackMapType object to visit
+ * @since 6.7.1
+ */
+ @Override
+ public void visitStackMapType(final StackMapType stackMapType) {
+ super.visitStackMapType(stackMapType);
+ printWriter.print("new StackMapType((byte)");
+ printWriter.print(stackMapType.getType());
+ printWriter.print(", ");
+ if (stackMapType.hasIndex()) {
+ printWriter.print("_cp.addClass(\"");
+ printWriter.print(stackMapType.getClassName());
+ printWriter.print("\")");
+ } else {
+ printWriter.print("-1");
+ }
+ printWriter.print(", _cp.getConstantPool())");
+ }
+
+ private void visitStackMapTypeArray(final StackMapType[] types) {
+ if (types == null || types.length == 0) {
+ printWriter.print("null"); // null translates to StackMapType.EMPTY_ARRAY
+ } else {
+ printWriter.print("new StackMapType[] {");
+ for (int i = 0; i < types.length; i++) {
+ types[i].accept(this);
+ if (i < types.length - 1) {
+ printWriter.print(", ");
+ } else {
+ printWriter.print(" }");
+ }
+ }
+ }
+ }
}
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
index f644c698b72..10d31974d47 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -53,7 +53,7 @@
* All subfiles reference each other appropriately, e.g. clicking on a method in the Method's frame will jump to the
* appropriate method in the Code frame.
*
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class Class2HTML {
@@ -73,7 +73,7 @@ public class Class2HTML {
basicTypes.add("float");
}
- public static void _main(final String[] argv) throws IOException {
+ public static void main(final String[] argv) throws IOException {
final String[] fileName = new String[argv.length];
int files = 0;
ClassParser parser = null;
@@ -89,7 +89,7 @@ public static void _main(final String[] argv) throws IOException {
if (argv[i].equals("-d")) { // Specify target directory, default '.'
dir = argv[++i];
if (!dir.endsWith("" + sep)) {
- dir = dir + sep;
+ dir += sep;
}
final File store = new File(dir);
if (!store.isDirectory()) {
@@ -115,7 +115,7 @@ public static void _main(final String[] argv) throws IOException {
if (zipFile == null) {
parser = new ClassParser(fileName[i]); // Create parser object from file
} else {
- parser = new ClassParser(zipFile, fileName[i]); // Create parser object from zip file
+ parser = new ClassParser(zipFile, fileName[i]); // Create parser object from ZIP file
}
javaClass = parser.parse();
new Class2HTML(javaClass, dir);
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
index 178ccc786b1..e95e8fbd0a0 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -30,7 +30,7 @@
* Utility class implementing a (type-safe) set of JavaClass objects. Since JavaClass has no equals() method, the name of the class is used for comparison.
*
* @see ClassStack
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
*/
public class ClassSet {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
index 723fc07509b..1935d724b3b 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java
@@ -542,7 +542,7 @@ private void writeMethod(final Method method, final int methodNumber) throws IOE
final String str = codeToHTML(stream, methodNumber);
String anchor = "";
/*
- * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very
+ * Sets an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very
* inefficient!
*/
if (gotoSet.get(offset)) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
index 5b045bf08cc..510fe4a03a6 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -63,14 +63,13 @@
*
* @see com.sun.org.apache.bcel.internal.generic.Instruction
* @see InstructionList
- * @LastModified: May 2021
+ * @LastModified: Sept 2025
*/
public class InstructionFinder {
/**
* Code patterns found may be checked using an additional user-defined constraint object whether they really match the
* needed criterion. I.e., check constraints that can not expressed with regular expressions.
- *
*/
public interface CodeConstraint {
@@ -374,7 +373,7 @@ public final Iterator search(final String pattern, final In
// }
// private static final String pattern2string( String pattern, boolean make_string ) {
-// StringBuffer buf = new StringBuffer();
+// StringBuilder buf = new StringBuilder();
// for (int i = 0; i < pattern.length(); i++) {
// char ch = pattern.charAt(i);
// if (ch >= OFFSET) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
index 8d1ddf493cd..c44e36d0a81 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
@@ -25,8 +25,8 @@
* Abstract definition of a class repository. Instances may be used to load classes from different sources and may be
* used in the Repository.setRepository method.
*
- * @see org.apache.bcel.Repository
- * @LastModified: Feb 2023
+ * @see com.sun.org.apache.bcel.internal.Repository
+ * @LastModified: Sept 2025
*/
public interface Repository {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java
new file mode 100644
index 00000000000..2bd92f155bc
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Utility classes for the Apache Byte Code Engineering Library (BCEL), namely:
+ *
+ * - Collection classes for JavaClass objects
+ * - A converter for class files to HTML
+ * - A tool to find instructions patterns via regular expressions
+ * - A class to find classes as defined in the CLASSPATH
+ * - A class loader that allows to create classes at run time
+ *
+ */
+package com.sun.org.apache.bcel.internal.util;
diff --git a/src/java.xml/share/classes/jdk/xml/internal/Utils.java b/src/java.xml/share/classes/jdk/xml/internal/Utils.java
index 439930be15d..ba857e8cc07 100644
--- a/src/java.xml/share/classes/jdk/xml/internal/Utils.java
+++ b/src/java.xml/share/classes/jdk/xml/internal/Utils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,10 @@
package jdk.xml.internal;
+import java.lang.reflect.Array;
import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
/**
* General utility. Use JdkXmlUtils for XML processing related functions.
@@ -54,4 +57,59 @@ public static Class>[] arraysAppend(final Class>[] original, final Class>.
System.arraycopy(items, 0, result, original.length, items.length);
return result;
}
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param array the specified array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static byte[] createEmptyArrayIfNull(byte[] array) {
+ return (array != null) ? array : new byte[0];
+ }
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param array the specified array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static int[] createEmptyArrayIfNull(int[] array) {
+ return (array != null) ? array : new int[0];
+ }
+
+ /**
+ * Returns the original array, or an empty array if it is {@code null}.
+ * @param the class type
+ * @param array the specified array
+ * @param type the type of the array
+ * @return the original array, or an empty array if it is {@code null}
+ */
+ public static T[] createEmptyArrayIfNull(final T[] array, final Class type) {
+ Objects.requireNonNull(type, "The type argument should not be null.");
+
+ return (array != null) ? array : type.cast(Array.newInstance(type.getComponentType(), 0));
+ }
+
+ /**
+ * Returns the new stream created by {@code Stream.of(values)} or an empty
+ * sequential stream created by {@code Stream.empty()} if values is null.
+ *
+ * @param the type of stream elements
+ * @param values the elements of the new stream
+ * @return the new stream created by {@code Stream.of(values)} or an empty
+ * sequential stream created by {@code Stream.empty()} if values is null.
+ */
+ @SafeVarargs
+ @SuppressWarnings("varargs") // Creating a stream from an array is safe
+ public static Stream streamOfIfNonNull(final T... values) {
+ return values == null ? Stream.empty() : Stream.of(values);
+ }
+
+ /**
+ * Checks if a CharSequence is empty ("") or null.
+ * @param cs the CharSequence to check, may be null
+ * @return {@code true} if the CharSequence is empty or null
+ */
+ public static boolean isEmpty(final CharSequence cs) {
+ return cs == null || cs.length() == 0;
+ }
}
diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md
index 2c673d6b1af..b64fc3640d4 100644
--- a/src/java.xml/share/legal/bcel.md
+++ b/src/java.xml/share/legal/bcel.md
@@ -1,4 +1,4 @@
-## Apache Commons Byte Code Engineering Library (BCEL) Version 6.7.0
+## Apache Commons Byte Code Engineering Library (BCEL) Version 6.10.0
### Apache Commons BCEL Notice