mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-28 15:51:02 +00:00
8336695: Update Commons BCEL to Version 6.10.0
Reviewed-by: lancea, naoto, iris
This commit is contained in:
parent
f62b9eca08
commit
3790965df3
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
@ -26,7 +26,7 @@ import jdk.xml.internal.Utils;
|
||||
* Exception constants.
|
||||
*
|
||||
* @since 6.0 (intended to replace the InstructionConstant interface)
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public final class ExceptionConst {
|
||||
|
||||
@ -52,7 +52,6 @@ public final class ExceptionConst {
|
||||
* Super class of any linking exception (aka Linkage Error)
|
||||
*/
|
||||
public static final Class<LinkageError> LINKING_EXCEPTION = LinkageError.class;
|
||||
|
||||
/**
|
||||
* Linking Exceptions
|
||||
*/
|
||||
@ -67,10 +66,10 @@ public final class ExceptionConst {
|
||||
public static final Class<NoSuchMethodError> NO_SUCH_METHOD_ERROR = NoSuchMethodError.class;
|
||||
public static final Class<NoClassDefFoundError> NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class;
|
||||
public static final Class<UnsatisfiedLinkError> UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class;
|
||||
|
||||
public static final Class<VerifyError> VERIFY_ERROR = VerifyError.class;
|
||||
/* UnsupportedClassVersionError is new in JDK 1.2 */
|
||||
// public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class;
|
||||
|
||||
/**
|
||||
* Run-Time Exceptions
|
||||
*/
|
||||
|
||||
@ -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,7 +30,7 @@ import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
|
||||
* @see com.sun.org.apache.bcel.internal.util.Repository
|
||||
* @see SyntheticRepository
|
||||
*
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public abstract class Repository {
|
||||
|
||||
@ -174,7 +174,7 @@ public abstract class Repository {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it.
|
||||
* Lookups class somewhere found on your CLASSPATH, or whereever the repository instance looks for it.
|
||||
*
|
||||
* @return class object for given fully qualified class name
|
||||
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
||||
|
||||
@ -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
|
||||
@ -25,27 +25,36 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* Super class for all objects that have modifiers like private, final, ... I.e.
|
||||
* classes, fields, and methods.
|
||||
*
|
||||
* @LastModified: Jan 2020
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public abstract class AccessFlags {
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
* Access flags.
|
||||
*
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int access_flags; // TODO not used externally at present
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*/
|
||||
public AccessFlags() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a initial access flags
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param accessFlags initial access flags.
|
||||
*/
|
||||
public AccessFlags(final int a) {
|
||||
access_flags = a;
|
||||
public AccessFlags(final int accessFlags) {
|
||||
access_flags = accessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets access flags.
|
||||
*
|
||||
* @return Access flags of the object aka. "modifiers".
|
||||
*/
|
||||
public final int getAccessFlags() {
|
||||
@ -53,142 +62,303 @@ public abstract class AccessFlags {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Access flags of the object aka. "modifiers".
|
||||
* Gets access flags.
|
||||
*
|
||||
* @return Access flags of the object also known as modifiers.
|
||||
*/
|
||||
public final int getModifiers() {
|
||||
return access_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the abstract bit is on.
|
||||
*
|
||||
* @return whether the abstract bit is on.
|
||||
*/
|
||||
public final boolean isAbstract() {
|
||||
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
||||
return test(Const.ACC_ABSTRACT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the abstract bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isAbstract(final boolean flag) {
|
||||
setFlag(Const.ACC_ABSTRACT, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the annotation bit is on.
|
||||
*
|
||||
* @return whether the annotation bit is on.
|
||||
*/
|
||||
public final boolean isAnnotation() {
|
||||
return (access_flags & Const.ACC_ANNOTATION) != 0;
|
||||
return test(Const.ACC_ANNOTATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the annotation bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isAnnotation(final boolean flag) {
|
||||
setFlag(Const.ACC_ANNOTATION, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the enum bit is on.
|
||||
*
|
||||
* @return whether the enum bit is on.
|
||||
*/
|
||||
public final boolean isEnum() {
|
||||
return (access_flags & Const.ACC_ENUM) != 0;
|
||||
return test(Const.ACC_ENUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the enum bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isEnum(final boolean flag) {
|
||||
setFlag(Const.ACC_ENUM, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the final bit is on.
|
||||
*
|
||||
* @return whether the final bit is on.
|
||||
*/
|
||||
public final boolean isFinal() {
|
||||
return (access_flags & Const.ACC_FINAL) != 0;
|
||||
return test(Const.ACC_FINAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the final bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isFinal(final boolean flag) {
|
||||
setFlag(Const.ACC_FINAL, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the interface bit is on.
|
||||
*
|
||||
* @return whether the interface bit is on.
|
||||
*/
|
||||
public final boolean isInterface() {
|
||||
return (access_flags & Const.ACC_INTERFACE) != 0;
|
||||
return test(Const.ACC_INTERFACE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interface bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isInterface(final boolean flag) {
|
||||
setFlag(Const.ACC_INTERFACE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the native bit is on.
|
||||
*
|
||||
* @return whether the native bit is on.
|
||||
*/
|
||||
public final boolean isNative() {
|
||||
return (access_flags & Const.ACC_NATIVE) != 0;
|
||||
return test(Const.ACC_NATIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the native bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isNative(final boolean flag) {
|
||||
setFlag(Const.ACC_NATIVE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the private bit is on.
|
||||
*
|
||||
* @return whether the private bit is on.
|
||||
*/
|
||||
public final boolean isPrivate() {
|
||||
return (access_flags & Const.ACC_PRIVATE) != 0;
|
||||
return test(Const.ACC_PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the private bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isPrivate(final boolean flag) {
|
||||
setFlag(Const.ACC_PRIVATE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the protected bit is on.
|
||||
*
|
||||
* @return whether the protected bit is on.
|
||||
*/
|
||||
public final boolean isProtected() {
|
||||
return (access_flags & Const.ACC_PROTECTED) != 0;
|
||||
return test(Const.ACC_PROTECTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the protected bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isProtected(final boolean flag) {
|
||||
setFlag(Const.ACC_PROTECTED, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the public bit is on.
|
||||
*
|
||||
* @return whether the public bit is on.
|
||||
*/
|
||||
public final boolean isPublic() {
|
||||
return (access_flags & Const.ACC_PUBLIC) != 0;
|
||||
return test(Const.ACC_PUBLIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the public bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isPublic(final boolean flag) {
|
||||
setFlag(Const.ACC_PUBLIC, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the static bit is on.
|
||||
*
|
||||
* @return whether the static bit is on.
|
||||
*/
|
||||
public final boolean isStatic() {
|
||||
return (access_flags & Const.ACC_STATIC) != 0;
|
||||
return test(Const.ACC_STATIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the static bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isStatic(final boolean flag) {
|
||||
setFlag(Const.ACC_STATIC, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the strict bit is on.
|
||||
*
|
||||
* @return whether the strict bit is on.
|
||||
*/
|
||||
public final boolean isStrictfp() {
|
||||
return (access_flags & Const.ACC_STRICT) != 0;
|
||||
return test(Const.ACC_STRICT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the strict bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isStrictfp(final boolean flag) {
|
||||
setFlag(Const.ACC_STRICT, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the synchronized bit is on.
|
||||
*
|
||||
* @return whether the synchronized bit is on.
|
||||
*/
|
||||
public final boolean isSynchronized() {
|
||||
return (access_flags & Const.ACC_SYNCHRONIZED) != 0;
|
||||
return test(Const.ACC_SYNCHRONIZED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the synchronized bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isSynchronized(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNCHRONIZED, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the synthetic bit is on.
|
||||
*
|
||||
* @return whether the synthetic bit is on.
|
||||
*/
|
||||
public final boolean isSynthetic() {
|
||||
return (access_flags & Const.ACC_SYNTHETIC) != 0;
|
||||
return test(Const.ACC_SYNTHETIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the synthetic bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isSynthetic(final boolean flag) {
|
||||
setFlag(Const.ACC_SYNTHETIC, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the transient bit is on.
|
||||
*
|
||||
* @return whether the varargs bit is on.
|
||||
*/
|
||||
public final boolean isTransient() {
|
||||
return (access_flags & Const.ACC_TRANSIENT) != 0;
|
||||
return test(Const.ACC_TRANSIENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the varargs bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isTransient(final boolean flag) {
|
||||
setFlag(Const.ACC_TRANSIENT, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the varargs bit is on.
|
||||
*
|
||||
* @return whether the varargs bit is on.
|
||||
*/
|
||||
public final boolean isVarArgs() {
|
||||
return (access_flags & Const.ACC_VARARGS) != 0;
|
||||
return test(Const.ACC_VARARGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the varargs bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isVarArgs(final boolean flag) {
|
||||
setFlag(Const.ACC_VARARGS, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the volatile bit is on.
|
||||
*
|
||||
* @return whether the volatile bit is on.
|
||||
*/
|
||||
public final boolean isVolatile() {
|
||||
return (access_flags & Const.ACC_VOLATILE) != 0;
|
||||
return test(Const.ACC_VOLATILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the volatile bit.
|
||||
*
|
||||
* @param flag The new value.
|
||||
*/
|
||||
public final void isVolatile(final boolean flag) {
|
||||
setFlag(Const.ACC_VOLATILE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
* Sets access flags also known as modifiers.
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
@ -207,11 +377,21 @@ public abstract class AccessFlags {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
* Sets access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setModifiers(final int accessFlags) {
|
||||
setAccessFlags(accessFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether the bit is on.
|
||||
*
|
||||
* @param test the bit to test.
|
||||
* @return whether the bit is on.
|
||||
*/
|
||||
private boolean test(final short test) {
|
||||
return (access_flags & test) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -27,20 +26,22 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.xml.internal.Utils;
|
||||
|
||||
/**
|
||||
* Represents one annotation in the annotation table
|
||||
*
|
||||
* @since 6.0
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class AnnotationEntry implements Node {
|
||||
|
||||
public static final AnnotationEntry[] EMPTY_ARRAY = {};
|
||||
|
||||
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
|
||||
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attributes) {
|
||||
// Find attributes that contain annotation data
|
||||
return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
|
||||
.toArray(AnnotationEntry[]::new);
|
||||
return Utils.streamOfIfNonNull(attributes).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
|
||||
.toArray(AnnotationEntry[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +56,6 @@ public class AnnotationEntry implements Node {
|
||||
public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException {
|
||||
final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible);
|
||||
final int numElementValuePairs = input.readUnsignedShort();
|
||||
annotationEntry.elementValuePairs = new ArrayList<>();
|
||||
for (int i = 0; i < numElementValuePairs; i++) {
|
||||
annotationEntry.elementValuePairs
|
||||
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
||||
@ -69,12 +69,13 @@ public class AnnotationEntry implements Node {
|
||||
|
||||
private final boolean isRuntimeVisible;
|
||||
|
||||
private List<ElementValuePair> elementValuePairs;
|
||||
private final List<ElementValuePair> elementValuePairs;
|
||||
|
||||
public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
this.typeIndex = typeIndex;
|
||||
this.constantPool = constantPool;
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
this.elementValuePairs = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -52,7 +52,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
|
||||
final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
super(annotationType, nameIndex, length, constantPool);
|
||||
this.annotationTable = annotationTable;
|
||||
setAnnotationTable(annotationTable);
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
}
|
||||
|
||||
@ -108,9 +108,6 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
* @return the number of annotation entries in this annotation
|
||||
*/
|
||||
public final int getNumAnnotations() {
|
||||
if (annotationTable == null) {
|
||||
return 0;
|
||||
}
|
||||
return annotationTable.length;
|
||||
}
|
||||
|
||||
@ -129,7 +126,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
* @param annotationTable the entries to set in this annotation
|
||||
*/
|
||||
public final void setAnnotationTable(final AnnotationEntry[] annotationTable) {
|
||||
this.annotationTable = annotationTable;
|
||||
this.annotationTable = annotationTable != null ? annotationTable : AnnotationEntry.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -151,9 +148,6 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
}
|
||||
|
||||
protected void writeAnnotations(final DataOutputStream dos) throws IOException {
|
||||
if (annotationTable == null) {
|
||||
return;
|
||||
}
|
||||
dos.writeShort(annotationTable.length);
|
||||
for (final AnnotationEntry element : annotationTable) {
|
||||
element.dump(dos);
|
||||
|
||||
@ -31,12 +31,12 @@ public class ArrayElementValue extends ElementValue {
|
||||
// For array types, this is the array
|
||||
private final ElementValue[] elementValues;
|
||||
|
||||
public ArrayElementValue(final int type, final ElementValue[] datums, final ConstantPool cpool) {
|
||||
public ArrayElementValue(final int type, final ElementValue[] elementValues, final ConstantPool cpool) {
|
||||
super(type, cpool);
|
||||
if (type != ARRAY) {
|
||||
throw new ClassFormatException("Only element values of type array can be built with this ctor - type specified: " + type);
|
||||
}
|
||||
this.elementValues = datums;
|
||||
this.elementValues = elementValues != null ? elementValues : EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* @see Synthetic
|
||||
* @see Deprecated
|
||||
* @see Signature
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public abstract class Attribute implements Cloneable, Node {
|
||||
private static final boolean debug = false;
|
||||
@ -181,6 +181,8 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
return new NestHost(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_MEMBERS:
|
||||
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RECORD:
|
||||
return new Record(nameIndex, length, dataInput, constantPool);
|
||||
default:
|
||||
// Never reached
|
||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
||||
@ -279,7 +281,7 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
try {
|
||||
attr = (Attribute) super.clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
throw new Error("Clone Not Supported"); // never happens
|
||||
throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
|
||||
}
|
||||
return attr;
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
/*
|
||||
* reserved comment block
|
||||
* DO NOT REMOVE OR ALTER!
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
@ -27,6 +26,7 @@ import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.Const;
|
||||
import jdk.xml.internal.Utils;
|
||||
|
||||
/**
|
||||
* This class represents a bootstrap method attribute, i.e., the bootstrap method ref, the number of bootstrap arguments
|
||||
@ -35,9 +35,12 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23"> The class File Format :
|
||||
* The BootstrapMethods Attribute</a>
|
||||
* @since 6.0
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class BootstrapMethod implements Cloneable {
|
||||
|
||||
static final BootstrapMethod[] EMPTY_ARRAY = {};
|
||||
|
||||
/** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */
|
||||
private int bootstrapMethodRef;
|
||||
|
||||
@ -54,7 +57,7 @@ public class BootstrapMethod implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* Constructs object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
@ -78,7 +81,7 @@ public class BootstrapMethod implements Cloneable {
|
||||
*/
|
||||
public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) {
|
||||
this.bootstrapMethodRef = bootstrapMethodRef;
|
||||
this.bootstrapArguments = bootstrapArguments;
|
||||
setBootstrapArguments(bootstrapArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,7 +90,7 @@ public class BootstrapMethod implements Cloneable {
|
||||
public BootstrapMethod copy() {
|
||||
try {
|
||||
return (BootstrapMethod) clone();
|
||||
} catch (final CloneNotSupportedException e) {
|
||||
} catch (final CloneNotSupportedException ignore) {
|
||||
// TODO should this throw?
|
||||
}
|
||||
return null;
|
||||
@ -132,7 +135,7 @@ public class BootstrapMethod implements Cloneable {
|
||||
* @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info
|
||||
*/
|
||||
public void setBootstrapArguments(final int[] bootstrapArguments) {
|
||||
this.bootstrapArguments = bootstrapArguments;
|
||||
this.bootstrapArguments = Utils.createEmptyArrayIfNull(bootstrapArguments);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -58,11 +58,11 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
*/
|
||||
public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool);
|
||||
this.bootstrapMethods = bootstrapMethods;
|
||||
setBootstrapMethods(bootstrapMethods);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -135,7 +135,7 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -47,12 +47,10 @@ public class ClassFormatException extends RuntimeException {
|
||||
|
||||
/**
|
||||
* Constructs a new instance with the specified detail message and cause.
|
||||
* <p>
|
||||
* Note that the detail message associated with {@code cause} is <i>not</i> 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 class ClassFormatException extends RuntimeException {
|
||||
* 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) {
|
||||
|
||||
@ -37,7 +37,7 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* appropriate exception is propagated back to the caller.
|
||||
*
|
||||
* The structure and the names comply, except for a few conveniences, exactly with the
|
||||
* <a href="http://docs.oracle.com/javase/specs/"> JVM specification 1.0</a>. See this paper for further details about
|
||||
* <a href="https://docs.oracle.com/javase/specs/"> JVM specification 1.0</a>. 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 final class ClassParser {
|
||||
/**
|
||||
* 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 final class ClassParser {
|
||||
/**
|
||||
* Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods,
|
||||
* fields and commands. A <em>ClassFormatException</em> 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 final class ClassParser {
|
||||
// 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));
|
||||
// }
|
||||
|
||||
@ -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 java.util.Arrays;
|
||||
|
||||
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 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* @see CodeException
|
||||
* @see LineNumberTable
|
||||
* @see LocalVariableTable
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public final class Code extends Attribute {
|
||||
|
||||
@ -93,7 +94,7 @@ public final class Code extends Attribute {
|
||||
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 final class Code extends Attribute {
|
||||
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 final class Code extends Attribute {
|
||||
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 final class Code extends Attribute {
|
||||
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 final class Code extends Attribute {
|
||||
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 final class Code extends Attribute {
|
||||
* @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 final class Code extends Attribute {
|
||||
* @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
|
||||
}
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* </pre>
|
||||
*
|
||||
* @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;
|
||||
|
||||
/**
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator;
|
||||
* 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<Constant> bcelComparator = new BCELComparator<Constant>() {
|
||||
|
||||
@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<Constant> getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
@ -113,7 +112,7 @@ public abstract class Constant implements Cloneable, Node {
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
public static void setComparator(final BCELComparator<Constant> comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
@ -148,7 +147,7 @@ public abstract class Constant implements Cloneable, Node {
|
||||
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 abstract class Constant implements Cloneable, Node {
|
||||
*/
|
||||
@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 abstract class Constant implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
|
||||
@ -29,7 +29,10 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*
|
||||
* @see Constant
|
||||
* @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
|
||||
@ -73,7 +73,7 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ConstantPool(final Constant[] constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
setConstantPool(constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +88,7 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
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 class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
*/
|
||||
public <T extends Constant> T getConstant(final int index, final byte tag, final Class<T> 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,15 +314,17 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
throw new ClassFormatException("Invalid constant pool reference at index: " + index +
|
||||
". Expected " + castTo + " but was " + constantPool[index].getClass());
|
||||
}
|
||||
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 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
|
||||
// the 0th element is always null
|
||||
&& index != 0) {
|
||||
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 (c == null) {
|
||||
throw new ClassFormatException("Constant pool at index " + index + " is null.");
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@ -402,7 +405,7 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
* @return Length of constant pool.
|
||||
*/
|
||||
public int getLength() {
|
||||
return constantPool == null ? 0 : constantPool.length;
|
||||
return constantPool.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -421,7 +424,7 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||
* @param constantPool
|
||||
*/
|
||||
public void setConstantPool(final Constant[] constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
this.constantPool = constantPool != null ? constantPool : Constant.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* The following system properties govern caching this class performs.
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>{@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
|
||||
* <li>{@link #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is
|
||||
* disabled.</li>
|
||||
* <li>{@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0
|
||||
* <li>{@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 <em>not</em> cached.</li>
|
||||
* <li>{@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.</li>
|
||||
* <li>{@link #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Here is a sample Maven invocation with caching disabled:
|
||||
@ -58,11 +58,11 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* </pre>
|
||||
*
|
||||
* @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 @@ public final class ConstantUtf8 extends Constant {
|
||||
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 @@ public final class ConstantUtf8 extends Constant {
|
||||
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.
|
||||
* <p>
|
||||
@ -203,7 +208,7 @@ public final class ConstantUtf8 extends Constant {
|
||||
ConstantUtf8(final DataInput dataInput) throws IOException {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
value = dataInput.readUTF();
|
||||
created++;
|
||||
countCreated();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,7 +217,7 @@ public final class ConstantUtf8 extends Constant {
|
||||
public ConstantUtf8(final String value) {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
this.value = Objects.requireNonNull(value, "value");
|
||||
created++;
|
||||
countCreated();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -56,7 +56,7 @@ public final class ConstantValue extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* Constructs object from input stream.
|
||||
*
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
|
||||
@ -59,7 +59,7 @@ public final class Deprecated extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@ -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 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
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 class DescendingVisitor implements Visitor {
|
||||
}
|
||||
|
||||
private <E extends Node> 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 class DescendingVisitor implements Visitor {
|
||||
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 class DescendingVisitor implements Visitor {
|
||||
|
||||
@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 class DescendingVisitor implements Visitor {
|
||||
attribute.accept(visitor);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*}
|
||||
*</pre>
|
||||
* @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 abstract class ElementValue {
|
||||
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);
|
||||
|
||||
|
||||
@ -315,6 +315,15 @@ public class EmptyVisitor implements Visitor {
|
||||
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) {
|
||||
}
|
||||
|
||||
@ -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 java.util.Arrays;
|
||||
|
||||
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 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* }
|
||||
* </pre>
|
||||
* @see Code
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public final class ExceptionTable extends Attribute {
|
||||
|
||||
@ -60,7 +61,7 @@ public final class ExceptionTable extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class ExceptionTable extends Attribute {
|
||||
*/
|
||||
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 final class ExceptionTable extends Attribute {
|
||||
* length.
|
||||
*/
|
||||
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY;
|
||||
this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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<Field> bcelComparator = new BCELComparator<Field>() {
|
||||
|
||||
@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<Field> 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<Field> 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 final class Field extends FieldOrMethod {
|
||||
*/
|
||||
@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 final class Field extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
@ -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 @@ import java.util.Arrays;
|
||||
/**
|
||||
* 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 @@ 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.
|
||||
@ -137,7 +137,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
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 abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
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 abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
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 extends Attribute> 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 abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
* @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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -42,7 +42,7 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final InnerClass[] EMPTY_INNER_CLASSE_ARRAY = {};
|
||||
private static final InnerClass[] EMPTY_ARRAY = {};
|
||||
|
||||
private InnerClass[] innerClasses;
|
||||
|
||||
@ -57,7 +57,7 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -82,7 +82,7 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
*/
|
||||
public InnerClasses(final int nameIndex, final int length, final InnerClass[] innerClasses, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_INNER_CLASSES, nameIndex, length, constantPool);
|
||||
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
|
||||
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_ARRAY;
|
||||
Args.requireU2(this.innerClasses.length, "innerClasses.length");
|
||||
}
|
||||
|
||||
@ -141,7 +141,7 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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.generic.Type;
|
||||
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 @@ import com.sun.org.apache.bcel.internal.util.SyntheticRepository;
|
||||
* classes should see the <a href="../generic/ClassGen.html">ClassGen</a> 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<JavaClass> {
|
||||
|
||||
@ -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<JavaClass> bcelComparator = new BCELComparator<JavaClass>() {
|
||||
|
||||
@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<JavaClass> getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
@ -100,9 +98,9 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
* @param comparator Comparison strategy object.
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
public static void setComparator(final BCELComparator<JavaClass> comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
@ -128,8 +126,10 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
return bcelComparator.equals(this, obj);
|
||||
return obj instanceof JavaClass && bcelComparator.equals(this, (JavaClass) obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all interfaces implemented by this JavaClass (transitively).
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
queue.enqueue(iface);
|
||||
}
|
||||
}
|
||||
return allInterfaces.toArray(JavaClass.EMPTY_ARRAY);
|
||||
return allInterfaces.toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -424,6 +475,22 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 extends Attribute> 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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
* @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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
* @param attributes .
|
||||
*/
|
||||
public void setAttributes(final Attribute[] attributes) {
|
||||
this.attributes = attributes;
|
||||
this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -734,11 +812,11 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
* @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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
* @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 class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
* @param methods .
|
||||
*/
|
||||
public void setMethods(final Method[] methods) {
|
||||
this.methods = methods;
|
||||
this.methods = methods != null ? methods : Method.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -787,7 +865,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 @@ import jdk.xml.internal.SecuritySupport;
|
||||
*
|
||||
* @see Code
|
||||
* @see LineNumber
|
||||
* @LastModified: May 2021
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public final class LineNumberTable extends Attribute implements Iterable<LineNumber> {
|
||||
|
||||
@ -44,7 +44,7 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
private LineNumber[] lineNumberTable; // Table of line/numbers pairs
|
||||
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
* Constructs a new instance from a data input stream.
|
||||
*
|
||||
* @param nameIndex Index of name
|
||||
* @param length Content length in bytes
|
||||
@ -61,13 +61,12 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param nameIndex Index of name
|
||||
*
|
||||
* @param length Content length in bytes
|
||||
*
|
||||
* @param lineNumberTable Table of line/numbers pairs
|
||||
*
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LineNumberTable(final int nameIndex, final int length, final LineNumber[] lineNumberTable, final ConstantPool constantPool) {
|
||||
@ -76,9 +75,11 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
Args.requireU2(this.lineNumberTable.length, "lineNumberTable.length");
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use copy() for a
|
||||
* physical copy.
|
||||
/**
|
||||
* Constructs a new instance from another.
|
||||
* <p>
|
||||
* Note that both objects use the same references (shallow copy). Use copy() for a physical copy.
|
||||
* </p>
|
||||
*/
|
||||
public LineNumberTable(final LineNumberTable c) {
|
||||
this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool());
|
||||
@ -190,7 +191,7 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
* @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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -40,10 +40,12 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
*/
|
||||
public class LocalVariableTable extends Attribute implements Iterable<LocalVariable> {
|
||||
|
||||
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<LocalVaria
|
||||
*/
|
||||
public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, constantPool);
|
||||
this.localVariableTable = localVariableTable != null ? localVariableTable : LocalVariable.EMPTY_ARRAY;
|
||||
this.localVariableTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
|
||||
Args.requireU2(this.localVariableTable.length, "localVariableTable.length");
|
||||
}
|
||||
|
||||
@ -167,7 +169,7 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
}
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTable == null ? 0 : localVariableTable.length;
|
||||
return localVariableTable.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,7 +178,7 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTable = localVariableTable;
|
||||
this.localVariableTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -63,14 +63,14 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
*/
|
||||
public class LocalVariableTypeTable extends Attribute implements Iterable<LocalVariable> {
|
||||
|
||||
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 class LocalVariableTypeTable extends Attribute implements Iterable<LocalV
|
||||
@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 class LocalVariableTypeTable extends Attribute implements Iterable<LocalV
|
||||
return variable;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -137,7 +135,7 @@ public class LocalVariableTypeTable extends Attribute implements Iterable<LocalV
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTypeTable = localVariableTable;
|
||||
this.localVariableTypeTable = localVariableTable != null ? localVariableTable : EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -146,15 +144,12 @@ public class LocalVariableTypeTable extends Attribute implements Iterable<LocalV
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<Method> bcelComparator = new BCELComparator<Method>() {
|
||||
|
||||
@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<Method> 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<Method> 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 final class Method extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class Method extends FieldOrMethod {
|
||||
*/
|
||||
@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 final class Method extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 final class Method extends FieldOrMethod {
|
||||
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 final class Method extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
|
||||
@ -29,6 +29,9 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Entry of the parameters table.
|
||||
* <p>
|
||||
* Implements {@link Node} as of 6.7.0.
|
||||
* </p>
|
||||
*
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.24"> The class File Format :
|
||||
* The MethodParameters Attribute</a>
|
||||
@ -46,7 +49,7 @@ public class MethodParameter implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MethodParameter implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MethodParameter implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
@ -42,13 +42,12 @@ public class MethodParameters extends Attribute implements Iterable<MethodParame
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final MethodParameter[] EMPTY_METHOD_PARAMETER_ARRAY = {};
|
||||
private static final MethodParameter[] EMPTY_ARRAY = {};
|
||||
|
||||
private MethodParameter[] parameters = EMPTY_METHOD_PARAMETER_ARRAY;
|
||||
private MethodParameter[] parameters = EMPTY_ARRAY;
|
||||
|
||||
MethodParameters(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
super(Const.ATTR_METHOD_PARAMETERS, nameIndex, length, constantPool);
|
||||
|
||||
final int parameterCount = input.readUnsignedByte();
|
||||
parameters = new MethodParameter[parameterCount];
|
||||
for (int i = 0; i < parameterCount; i++) {
|
||||
@ -65,7 +64,6 @@ public class MethodParameters extends Attribute implements Iterable<MethodParame
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
final MethodParameters c = (MethodParameters) clone();
|
||||
c.parameters = new MethodParameter[parameters.length];
|
||||
|
||||
Arrays.setAll(c.parameters, i -> parameters[i].copy());
|
||||
c.setConstantPool(constantPool);
|
||||
return c;
|
||||
@ -96,6 +94,6 @@ public class MethodParameters extends Attribute implements Iterable<MethodParame
|
||||
}
|
||||
|
||||
public void setParameters(final MethodParameter[] parameters) {
|
||||
this.parameters = parameters;
|
||||
this.parameters = parameters != null ? parameters : EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 final class Module extends Attribute {
|
||||
v.visitModule(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@ -186,6 +192,25 @@ public final class Module extends Attribute {
|
||||
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 final class Module extends Attribute {
|
||||
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 final class Module extends Attribute {
|
||||
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 final class Module extends Attribute {
|
||||
|
||||
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");
|
||||
|
||||
@ -36,13 +36,17 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*/
|
||||
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 final class ModuleExports implements Cloneable, Node {
|
||||
v.visitModuleExports(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@ -97,6 +99,39 @@ public final class ModuleExports implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class ModuleExports implements Cloneable, Node {
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -36,13 +36,17 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*/
|
||||
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 final class ModuleOpens implements Cloneable, Node {
|
||||
v.visitModuleOpens(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@ -97,6 +99,39 @@ public final class ModuleOpens implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class ModuleOpens implements Cloneable, Node {
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
@ -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 java.util.Arrays;
|
||||
|
||||
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 <em>Attribute</em> 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 final class ModulePackages extends Attribute {
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -36,12 +36,20 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*/
|
||||
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 final class ModuleProvides implements Cloneable, Node {
|
||||
v.visitModuleProvides(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@ -94,6 +100,31 @@ public final class ModuleProvides implements Cloneable, Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class ModuleProvides implements Cloneable, Node {
|
||||
*/
|
||||
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
|
||||
}
|
||||
|
||||
@ -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 final class ModuleRequires implements Cloneable, Node {
|
||||
v.visitModuleRequires(this);
|
||||
}
|
||||
|
||||
// TODO add more getters and setters?
|
||||
|
||||
/**
|
||||
* @return deep copy of this object
|
||||
*/
|
||||
@ -89,6 +87,35 @@ public final class ModuleRequires implements Cloneable, Node {
|
||||
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 final class ModuleRequires implements Cloneable, Node {
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
@ -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 java.util.Arrays;
|
||||
|
||||
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 <em>Attribute</em> and records the classes and interfaces that are authorized to claim
|
||||
@ -34,14 +35,14 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* 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 final class NestMembers extends Attribute {
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -26,5 +26,5 @@ package com.sun.org.apache.bcel.internal.classfile;
|
||||
*/
|
||||
public interface Node {
|
||||
|
||||
void accept(Visitor obj);
|
||||
void accept(Visitor visitor);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<ParameterAnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
||||
for (final Attribute attribute : attrs) {
|
||||
final List<ParameterAnnotationEntry> 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.
|
||||
|
||||
@ -34,10 +34,14 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
public abstract class ParameterAnnotations extends Attribute implements Iterable<ParameterAnnotationEntry> {
|
||||
|
||||
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 <em>Code</em>
|
||||
* @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 <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
@ -120,6 +126,6 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 <a href="https://docs.oracle.com/javase/specs/jvms/se14/preview/specs/records-jvms.html#jvms-4.7.30">
|
||||
* The Java Virtual Machine Specification, Java SE 14 Edition, Records (preview)</a>
|
||||
* @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
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,13 +28,15 @@ import java.io.IOException;
|
||||
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 <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
@ -46,7 +48,9 @@ public class RuntimeInvisibleAnnotations extends Annotations {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
|
||||
@ -34,6 +34,8 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
|
||||
@ -28,13 +28,15 @@ import java.io.IOException;
|
||||
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 <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
@ -46,7 +48,9 @@ public class RuntimeVisibleAnnotations extends Annotations {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
|
||||
@ -34,6 +34,8 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
|
||||
@ -110,7 +110,7 @@ public final class Signature extends Attribute {
|
||||
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 @@ public final class Signature extends Attribute {
|
||||
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 @@ public final class Signature extends Attribute {
|
||||
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 final class Signature extends Attribute {
|
||||
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
|
||||
|
||||
@ -54,7 +54,7 @@ public class SimpleElementValue extends ElementValue {
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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 class SimpleElementValue extends ElementValue {
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
|
||||
/**
|
||||
* This class represents a stack map attribute used for preverification of Java classes for the
|
||||
* <a href="http://java.sun.com/j2me/"> Java 2 Micro Edition</a> (J2ME). This attribute is used by the
|
||||
* <a href="http://java.sun.com/products/cldc/">KVM</a> and contained within the Code attribute of a method. See CLDC
|
||||
* <a href="https://java.sun.com/j2me/"> Java 2 Micro Edition</a> (J2ME). This attribute is used by the
|
||||
* <a href="https://java.sun.com/products/cldc/">KVM</a> and contained within the Code attribute of a method. See CLDC
|
||||
* specification 5.3.1.2
|
||||
*
|
||||
* <pre>
|
||||
@ -46,14 +46,14 @@ import com.sun.org.apache.bcel.internal.util.Args;
|
||||
* @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
|
||||
|
||||
@ -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 final class StackMapEntry implements Node, Cloneable {
|
||||
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 final class StackMapEntry implements Node, Cloneable {
|
||||
} 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 final class StackMapEntry implements Node, Cloneable {
|
||||
|
||||
/**
|
||||
* Calculate stack map entry size
|
||||
*
|
||||
*/
|
||||
int getMapEntrySize() {
|
||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||
|
||||
@ -34,9 +34,9 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
* @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 final class StackMapType implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 final class StackMapType implements Cloneable {
|
||||
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 final class StackMapType implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public final class StackMapType implements Cloneable {
|
||||
if (index < 0) {
|
||||
return ", class=<unknown>";
|
||||
}
|
||||
return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
|
||||
return ", class=" + getClassName();
|
||||
}
|
||||
if (type == Const.ITEM_NewObject) {
|
||||
return ", offset=" + index;
|
||||
|
||||
@ -52,7 +52,7 @@ public final class Synthetic extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
/**
|
||||
* 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 <a href="Utility.html#decode(java.lang.String, boolean)">decode()</a>
|
||||
*/
|
||||
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 abstract class Utility {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode bytes into valid java identifier characters. Used by
|
||||
* Encode bytes into valid Java identifier characters. Used by
|
||||
* <a href="Utility.html#encode(byte[], boolean)">encode()</a>
|
||||
*/
|
||||
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 abstract class Utility {
|
||||
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 abstract class Utility {
|
||||
// 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 abstract class Utility {
|
||||
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 abstract class Utility {
|
||||
// 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 abstract class Utility {
|
||||
// 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 abstract class Utility {
|
||||
// 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 abstract class Utility {
|
||||
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 abstract class Utility {
|
||||
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 abstract class Utility {
|
||||
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 abstract class Utility {
|
||||
} 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 abstract class Utility {
|
||||
} 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 abstract class Utility {
|
||||
// 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 abstract class Utility {
|
||||
// The rest of the string denotes a '<field_type>'
|
||||
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 abstract class Utility {
|
||||
}
|
||||
|
||||
private static int unwrap(final ThreadLocal<Integer> tl) {
|
||||
return tl.get();
|
||||
return tl.get().intValue();
|
||||
}
|
||||
|
||||
private static void wrap(final ThreadLocal<Integer> tl, final int value) {
|
||||
tl.set(value);
|
||||
tl.set(Integer.valueOf(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -217,11 +217,32 @@ public interface Visitor {
|
||||
*/
|
||||
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 @@ public interface Visitor {
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.ExceptionConst;
|
||||
* <PRE>
|
||||
* Stack: ..., arrayref -> ..., length
|
||||
* </PRE>
|
||||
* @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);
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.ExceptionConst;
|
||||
* <PRE>
|
||||
* Stack: ..., objectref -> objectref
|
||||
* </PRE>
|
||||
*
|
||||
* @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 class ATHROW extends Instruction implements UnconditionalBranch, Exceptio
|
||||
public void accept(final Visitor v) {
|
||||
v.visitUnconditionalBranch(this);
|
||||
v.visitExceptionThrower(this);
|
||||
v.visitStackConsumer(this);
|
||||
v.visitATHROW(this);
|
||||
}
|
||||
|
||||
|
||||
@ -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.DataOutputStream;
|
||||
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.RuntimeInvisibleAnnotations;
|
||||
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 class AnnotationEntryGen {
|
||||
}
|
||||
|
||||
private List<ElementValuePairGen> copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
||||
final List<ElementValuePairGen> 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 class AnnotationEntryGen {
|
||||
}
|
||||
|
||||
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<ElementValuePairGen> getValues() {
|
||||
return evs;
|
||||
|
||||
@ -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.DataOutputStream;
|
||||
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 class ArrayElementValueGen extends ElementValueGen {
|
||||
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 class ArrayElementValueGen extends ElementValueGen {
|
||||
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) {
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
|
||||
/**
|
||||
* Denotes array type, such as int[][]
|
||||
*
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public final class ArrayType extends ReferenceType {
|
||||
|
||||
@ -43,7 +44,7 @@ public final class ArrayType extends ReferenceType {
|
||||
/**
|
||||
* 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 final class ArrayType extends ReferenceType {
|
||||
* @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, "<dummy>");
|
||||
if (dimensions < 1 || dimensions > Const.MAX_BYTE) {
|
||||
@ -79,7 +81,7 @@ public final class ArrayType extends ReferenceType {
|
||||
buf.append('[');
|
||||
}
|
||||
buf.append(basicType.getSignature());
|
||||
super.setSignature(buf.toString());
|
||||
this.signature = buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -63,7 +63,7 @@ public final class BranchHandle extends InstructionHandle {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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?
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
* @see LDC
|
||||
* @see INVOKEVIRTUAL
|
||||
*
|
||||
* @LastModified: Jan 2020
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction {
|
||||
|
||||
@ -104,7 +104,7 @@ public abstract class CPInstruction extends Instruction implements TypedInstruct
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the index to constant pool.
|
||||
* Sets the index to constant pool.
|
||||
*
|
||||
* @param index in constant pool.
|
||||
*/
|
||||
|
||||
@ -48,12 +48,12 @@ public class ClassElementValueGen extends ElementValueGen {
|
||||
}
|
||||
|
||||
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 class ClassElementValueGen extends ElementValueGen {
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@ -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.classfile.Utility;
|
||||
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<ClassGen> bcelComparator = new BCELComparator<ClassGen>() {
|
||||
|
||||
@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<ClassGen> getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
public static void setComparator(final BCELComparator<ClassGen> comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
@ -101,7 +98,7 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
||||
private List<ClassObserver> 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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
*/
|
||||
@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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
|
||||
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 class ClassGen extends AccessFlags implements Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<AnnotationEntryGen> 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);
|
||||
|
||||
@ -63,7 +63,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
||||
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 final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CodeException object.<BR>
|
||||
* Gets CodeException object.<BR>
|
||||
*
|
||||
* 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 final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
||||
}
|
||||
|
||||
/*
|
||||
* Set end of handler
|
||||
* Sets end of handler
|
||||
*
|
||||
* @param endPc End of handled region (inclusive)
|
||||
*/
|
||||
@ -130,7 +130,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
||||
}
|
||||
|
||||
/*
|
||||
* Set handler code
|
||||
* Sets handler code
|
||||
*
|
||||
* @param handlerPc Start of handler
|
||||
*/
|
||||
@ -140,7 +140,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
||||
}
|
||||
|
||||
/*
|
||||
* Set start of handler
|
||||
* Sets start of handler
|
||||
*
|
||||
* @param startPc Start of handled region (inclusive)
|
||||
*/
|
||||
|
||||
@ -44,7 +44,7 @@ public class ElementValuePairGen {
|
||||
// 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 class ElementValuePairGen {
|
||||
}
|
||||
|
||||
public final String getNameString() {
|
||||
// ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx);
|
||||
// ConstantString cu8 = (ConstantString) constantPoolGen.getConstant(nameIdx);
|
||||
return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes();
|
||||
}
|
||||
|
||||
|
||||
@ -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 class EnumElementValueGen extends ElementValueGen {
|
||||
* 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 @@ public class EnumElementValueGen extends ElementValueGen {
|
||||
}
|
||||
|
||||
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 class EnumElementValueGen extends ElementValueGen {
|
||||
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 class EnumElementValueGen extends ElementValueGen {
|
||||
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 class EnumElementValueGen extends ElementValueGen {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
|
||||
/**
|
||||
* 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 <i>RUN-TIME</i> and which <i>LINKING</i> exceptions each
|
||||
* instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator;
|
||||
* 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<FieldGen> bcelComparator = new BCELComparator<FieldGen>() {
|
||||
|
||||
@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<FieldGen> 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<FieldGen> comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
@ -81,8 +78,8 @@ public class FieldGen extends FieldGenOrMethodGen {
|
||||
/**
|
||||
* 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 class FieldGen extends FieldGenOrMethodGen {
|
||||
*/
|
||||
@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 class FieldGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
public String getInitValue() {
|
||||
if (value != null) {
|
||||
return value.toString();
|
||||
}
|
||||
return null;
|
||||
return Objects.toString(value, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -219,7 +213,7 @@ public class FieldGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class FieldGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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"));
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.classfile.Attribute;
|
||||
/**
|
||||
* 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 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
||||
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 abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,7 +53,6 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
|
||||
* 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 abstract class FieldOrMethod extends CPInstruction implements LoadClass {
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
* <PRE>
|
||||
* Stack: ... -> ...,
|
||||
* </PRE>
|
||||
*
|
||||
*/
|
||||
public class ICONST extends Instruction implements ConstantPushInstruction {
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.invokedynamic"> The
|
||||
* invokedynamic instruction in The Java Virtual Machine Specification</a>
|
||||
* @since 6.0
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class INVOKEDYNAMIC extends InvokeInstruction {
|
||||
|
||||
@ -104,11 +104,11 @@ public class INVOKEDYNAMIC extends InvokeInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
/**
|
||||
* 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 abstract class Instruction implements Cloneable {
|
||||
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 {
|
||||
|
||||
@ -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];
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.Const;
|
||||
*
|
||||
* @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 @@ public class InstructionFactory {
|
||||
|
||||
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 class InstructionFactory {
|
||||
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 class InstructionFactory {
|
||||
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 class InstructionFactory {
|
||||
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 class InstructionFactory {
|
||||
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);
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.classfile.Utility;
|
||||
* @see Instruction
|
||||
* @see BranchHandle
|
||||
* @see InstructionList
|
||||
* @LastModified: May 2021
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class InstructionHandle {
|
||||
|
||||
@ -118,7 +118,7 @@ public class InstructionHandle {
|
||||
if (targeters == null) {
|
||||
targeters = new HashSet<>();
|
||||
}
|
||||
// if(!targeters.contains(t))
|
||||
// if (!targeters.contains(t))
|
||||
targeters.add(t);
|
||||
}
|
||||
|
||||
@ -135,15 +135,12 @@ public class InstructionHandle {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 @@ public class InstructionHandle {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@ -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 java.util.NoSuchElementException;
|
||||
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 <a href="Instruction.html">Instruction</a> objects. Instructions can be
|
||||
@ -46,7 +47,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
* @see Instruction
|
||||
* @see InstructionHandle
|
||||
* @see BranchHandle
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class InstructionList implements Iterable<InstructionHandle> {
|
||||
|
||||
@ -60,23 +61,25 @@ public class InstructionList implements Iterable<InstructionHandle> {
|
||||
* @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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
* @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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
if (exception.getHandlerPC() == oldTarget) {
|
||||
exception.setHandlerPC(newTarget);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -981,16 +984,14 @@ public class InstructionList implements Iterable<InstructionHandle> {
|
||||
* @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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
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 class InstructionList implements Iterable<InstructionHandle> {
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -27,7 +27,6 @@ package com.sun.org.apache.bcel.internal.generic;
|
||||
* <PRE>
|
||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
|
||||
* </PRE>
|
||||
*
|
||||
*/
|
||||
public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer {
|
||||
|
||||
|
||||
@ -94,6 +94,8 @@ public class LDC extends CPInstruction implements PushInstruction, ExceptionThro
|
||||
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 class LDC extends CPInstruction implements PushInstruction, ExceptionThro
|
||||
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 @@ public class LDC extends CPInstruction implements PushInstruction, ExceptionThro
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
@ -54,7 +54,7 @@ public class LineNumberGen implements InstructionTargeter, Cloneable {
|
||||
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 class LineNumberGen implements InstructionTargeter, Cloneable {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@ -85,7 +85,7 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
|
||||
/**
|
||||
* 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 @@ public abstract class LocalVariableInstruction extends Instruction implements Ty
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
*/
|
||||
|
||||
@ -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.HashMap;
|
||||
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.ParameterAnnotations;
|
||||
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 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator;
|
||||
*
|
||||
* @see InstructionList
|
||||
* @see Method
|
||||
* @LastModified: Feb 2023
|
||||
* @LastModified: Sept 2025
|
||||
*/
|
||||
public class MethodGen extends FieldGenOrMethodGen {
|
||||
|
||||
@ -102,19 +104,16 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
}
|
||||
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
private static BCELComparator<FieldGenOrMethodGen> bcelComparator = new BCELComparator<FieldGenOrMethodGen>() {
|
||||
|
||||
@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 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
* @return Comparison strategy object.
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
public static BCELComparator<FieldGenOrMethodGen> getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
@ -206,9 +205,9 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
* @param comparator Comparison strategy object.
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
public static void setComparator(final BCELComparator<FieldGenOrMethodGen> comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
@ -636,7 +635,7 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
*/
|
||||
@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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
private List<AnnotationEntryGen> makeMutableVersion(final AnnotationEntry[] mutableArray) {
|
||||
final List<AnnotationEntryGen> 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 class MethodGen extends FieldGenOrMethodGen {
|
||||
*
|
||||
* @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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 class MethodGen extends FieldGenOrMethodGen {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user