mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-04-08 00:57:32 +00:00
refactor
This commit is contained in:
9
pom.xml
9
pom.xml
@@ -43,6 +43,13 @@
|
||||
<version>2.0.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.26</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -68,7 +75,7 @@
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>haidnor.jvm.Main</mainClass>
|
||||
<mainClass>haidnor.jvm.HaidnorJVM</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
|
||||
83
src/main/java/haidnor/jvm/HaidnorJVM.java
Normal file
83
src/main/java/haidnor/jvm/HaidnorJVM.java
Normal file
@@ -0,0 +1,83 @@
|
||||
package haidnor.jvm;
|
||||
|
||||
import haidnor.jvm.bcel.classfile.JavaClass;
|
||||
import haidnor.jvm.classloader.JVMClassLoader;
|
||||
import haidnor.jvm.core.JavaExecutionEngine;
|
||||
import haidnor.jvm.rtda.Metaspace;
|
||||
import haidnor.jvm.runtime.JVMThread;
|
||||
import haidnor.jvm.util.JVMThreadHolder;
|
||||
import lombok.SneakyThrows;
|
||||
import org.apache.commons.cli.*;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/FranzHaidnor">GitHub FranzHaidnor</a>
|
||||
*/
|
||||
public class HaidnorJVM {
|
||||
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
String banner = """
|
||||
██╗ ██╗ █████╗ ██╗██████╗ ███╗ ██╗ ██████╗ ██████╗ ██╗██╗ ██╗███╗ ███╗
|
||||
██║ ██║██╔══██╗██║██╔══██╗████╗ ██║██╔═══██╗██╔══██╗ ██║██║ ██║████╗ ████║
|
||||
███████║███████║██║██║ ██║██╔██╗ ██║██║ ██║██████╔╝ ██║██║ ██║██╔████╔██║
|
||||
██╔══██║██╔══██║██║██║ ██║██║╚██╗██║██║ ██║██╔══██╗ ██ ██║╚██╗ ██╔╝██║╚██╔╝██║
|
||||
██║ ██║██║ ██║██║██████╔╝██║ ╚████║╚██████╔╝██║ ██║ ╚█████╔╝ ╚████╔╝ ██║ ╚═╝ ██║
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚════╝ ╚═══╝ ╚═╝ ╚═╝
|
||||
""";
|
||||
System.out.println(banner);
|
||||
|
||||
CommandLine cmd = initCommandLine(args);
|
||||
|
||||
// 指定从 .jar 文件运行
|
||||
if (cmd.hasOption("jar")) {
|
||||
String jarFilePath = cmd.getOptionValue("jar");
|
||||
try (JarFile jarFile = new JarFile(jarFilePath)) {
|
||||
JVMClassLoader classLoader = new JVMClassLoader(jarFile, "ApplicationClassLoader");
|
||||
String mainClass = jarFile.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
if (!entry.isDirectory() && entry.getName().endsWith(".class")) {
|
||||
String className = entry.getName().replace('/', '.').substring(0, entry.getName().length() - 6);
|
||||
if (className.equals(mainClass)) {
|
||||
JVMThreadHolder.set(new JVMThread());
|
||||
JavaClass javaClass = classLoader.loadWithJar(jarFile, entry);
|
||||
Metaspace.registerJavaClass(javaClass);
|
||||
JavaExecutionEngine.callMainMethod(javaClass);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 指定从 .class 文件运行
|
||||
if (cmd.hasOption("class")) {
|
||||
JVMThreadHolder.set(new JVMThread());
|
||||
String path = cmd.getOptionValue("class");
|
||||
JVMClassLoader bootClassLoader = new JVMClassLoader("ApplicationClassLoader");
|
||||
JavaClass javaClass = bootClassLoader.loadWithAbsolutePath(path);
|
||||
JavaExecutionEngine.callMainMethod(javaClass);
|
||||
}
|
||||
}
|
||||
|
||||
private static CommandLine initCommandLine(String[] args) throws ParseException {
|
||||
Option jarOption = new Option("jar", true, "运行 jar 程序");
|
||||
Option classOption = new Option("class", true, "运行 .class 字节码文件");
|
||||
|
||||
OptionGroup optionGroup = new OptionGroup();
|
||||
optionGroup.addOption(jarOption).addOption(classOption);
|
||||
|
||||
Options options = new Options();
|
||||
options.addOptionGroup(optionGroup);
|
||||
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
return parser.parse(options, args);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,24 +25,14 @@ import org.apache.commons.lang3.ArrayUtils;
|
||||
*/
|
||||
public final class ExceptionConst {
|
||||
|
||||
/**
|
||||
* Enum corresponding to the various Exception Class arrays, used by
|
||||
* {@link ExceptionConst#createExceptions(EXCS, Class...)}
|
||||
*/
|
||||
public enum EXCS {
|
||||
EXCS_CLASS_AND_INTERFACE_RESOLUTION, EXCS_FIELD_AND_METHOD_RESOLUTION, EXCS_INTERFACE_METHOD_RESOLUTION, EXCS_STRING_RESOLUTION, EXCS_ARRAY_EXCEPTION,
|
||||
}
|
||||
|
||||
/**
|
||||
* The mother of all exceptions
|
||||
*/
|
||||
public static final Class<Throwable> THROWABLE = Throwable.class;
|
||||
|
||||
/**
|
||||
* Super class of any run-time exception
|
||||
*/
|
||||
public static final Class<RuntimeException> RUNTIME_EXCEPTION = RuntimeException.class;
|
||||
|
||||
/**
|
||||
* Super class of any linking exception (aka Linkage Error)
|
||||
*/
|
||||
@@ -61,62 +51,56 @@ 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
|
||||
*/
|
||||
public static final Class<NullPointerException> NULL_POINTER_EXCEPTION = NullPointerException.class;
|
||||
/* UnsupportedClassVersionError is new in JDK 1.2 */
|
||||
// public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class;
|
||||
public static final Class<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
|
||||
public static final Class<ArithmeticException> ARITHMETIC_EXCEPTION = ArithmeticException.class;
|
||||
public static final Class<NegativeArraySizeException> NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
|
||||
public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class;
|
||||
|
||||
public static final Class<IllegalMonitorStateException> ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.class;
|
||||
/**
|
||||
* Pre-defined exception arrays according to chapters 5.1-5.4 of the Java Virtual Machine Specification
|
||||
*/
|
||||
private static final Class<?>[] EXCS_CLASS_AND_INTERFACE_RESOLUTION = {NO_CLASS_DEF_FOUND_ERROR, CLASS_FORMAT_ERROR, VERIFY_ERROR, ABSTRACT_METHOD_ERROR,
|
||||
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR}; // Chapter 5.1
|
||||
|
||||
EXCEPTION_IN_INITIALIZER_ERROR, ILLEGAL_ACCESS_ERROR}; // Chapter 5.1
|
||||
private static final Class<?>[] EXCS_FIELD_AND_METHOD_RESOLUTION = {NO_SUCH_FIELD_ERROR, ILLEGAL_ACCESS_ERROR, NO_SUCH_METHOD_ERROR}; // Chapter 5.2
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final Class<?>[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
private static final Class<?>[] EXCS_STRING_RESOLUTION = new Class[0];
|
||||
|
||||
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
||||
private static final Class<?>[] EXCS_ARRAY_EXCEPTION = {NULL_POINTER_EXCEPTION, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION};
|
||||
|
||||
/**
|
||||
* Creates a copy of the specified Exception Class array combined with any additional Exception classes.
|
||||
*
|
||||
* @param type the basic array type
|
||||
* @param type the basic array type
|
||||
* @param extraClasses additional classes, if any
|
||||
* @return the merged array
|
||||
*/
|
||||
public static Class<?>[] createExceptions(final EXCS type, final Class<?>... extraClasses) {
|
||||
switch (type) {
|
||||
case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
|
||||
return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
|
||||
case EXCS_ARRAY_EXCEPTION:
|
||||
return mergeExceptions(EXCS_ARRAY_EXCEPTION, extraClasses);
|
||||
case EXCS_FIELD_AND_METHOD_RESOLUTION:
|
||||
return mergeExceptions(EXCS_FIELD_AND_METHOD_RESOLUTION, extraClasses);
|
||||
case EXCS_INTERFACE_METHOD_RESOLUTION:
|
||||
return mergeExceptions(EXCS_INTERFACE_METHOD_RESOLUTION, extraClasses);
|
||||
case EXCS_STRING_RESOLUTION:
|
||||
return mergeExceptions(EXCS_STRING_RESOLUTION, extraClasses);
|
||||
default:
|
||||
throw new AssertionError("Cannot happen; unexpected enum value: " + type);
|
||||
case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
|
||||
return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
|
||||
case EXCS_ARRAY_EXCEPTION:
|
||||
return mergeExceptions(EXCS_ARRAY_EXCEPTION, extraClasses);
|
||||
case EXCS_FIELD_AND_METHOD_RESOLUTION:
|
||||
return mergeExceptions(EXCS_FIELD_AND_METHOD_RESOLUTION, extraClasses);
|
||||
case EXCS_INTERFACE_METHOD_RESOLUTION:
|
||||
return mergeExceptions(EXCS_INTERFACE_METHOD_RESOLUTION, extraClasses);
|
||||
case EXCS_STRING_RESOLUTION:
|
||||
return mergeExceptions(EXCS_STRING_RESOLUTION, extraClasses);
|
||||
default:
|
||||
throw new AssertionError("Cannot happen; unexpected enum value: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,4 +109,12 @@ public final class ExceptionConst {
|
||||
return ArrayUtils.addAll(input, extraClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enum corresponding to the various Exception Class arrays, used by
|
||||
* {@link ExceptionConst#createExceptions(EXCS, Class...)}
|
||||
*/
|
||||
public enum EXCS {
|
||||
EXCS_CLASS_AND_INTERFACE_RESOLUTION, EXCS_FIELD_AND_METHOD_RESOLUTION, EXCS_INTERFACE_METHOD_RESOLUTION, EXCS_STRING_RESOLUTION, EXCS_ARRAY_EXCEPTION,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class Repository {
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super classes and the interfaces that those interfaces extend,
|
||||
* and so on. (Some people call this a transitive hull).
|
||||
* and so on. (Some people call this a transitive hull).
|
||||
* @throws ClassNotFoundException if any of the class's superclasses or superinterfaces can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
|
||||
@@ -62,9 +62,9 @@ public abstract class Repository {
|
||||
|
||||
/**
|
||||
* @return all interfaces implemented by class and its super classes and the interfaces that extend those interfaces,
|
||||
* and so on
|
||||
* and so on
|
||||
* @throws ClassNotFoundException if the named class can't be found, or if any of its superclasses or superinterfaces
|
||||
* can't be found
|
||||
* can't be found
|
||||
*/
|
||||
public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
|
||||
return getInterfaces(lookupClass(className));
|
||||
@@ -77,6 +77,13 @@ public abstract class Repository {
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets repository instance to be used for class loading
|
||||
*/
|
||||
public static void setRepository(final haidnor.jvm.bcel.util.Repository rep) {
|
||||
repository = rep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list of super classes of clazz in ascending order, i.e., Object is always the last element
|
||||
* @throws ClassNotFoundException if any of the superclasses can't be found
|
||||
@@ -162,9 +169,9 @@ public abstract class Repository {
|
||||
/**
|
||||
* Tries to find class source using the internal repository instance.
|
||||
*
|
||||
* @see Class
|
||||
* @return JavaClass object for given runtime class
|
||||
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
||||
* @see Class
|
||||
*/
|
||||
public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
|
||||
return repository.loadClass(clazz);
|
||||
@@ -182,7 +189,7 @@ public abstract class Repository {
|
||||
|
||||
/**
|
||||
* @return class file object for given Java class by looking on the system class path; returns null if the class file
|
||||
* can't be found
|
||||
* can't be found
|
||||
*/
|
||||
public static ClassPath.ClassFile lookupClassFile(final String className) {
|
||||
try (ClassPath path = repository.getClassPath()) {
|
||||
@@ -205,11 +212,4 @@ public abstract class Repository {
|
||||
public static void removeClass(final String clazz) {
|
||||
repository.removeClass(repository.findClass(clazz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets repository instance to be used for class loading
|
||||
*/
|
||||
public static void setRepository(final haidnor.jvm.bcel.util.Repository rep) {
|
||||
repository = rep;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,15 @@ public abstract class AccessFlags {
|
||||
return access_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setAccessFlags(final int accessFlags) {
|
||||
this.access_flags = accessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Access flags of the object aka. "modifiers".
|
||||
*/
|
||||
@@ -53,6 +62,15 @@ public abstract class AccessFlags {
|
||||
return access_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setModifiers(final int accessFlags) {
|
||||
setAccessFlags(accessFlags);
|
||||
}
|
||||
|
||||
public final boolean isAbstract() {
|
||||
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
||||
}
|
||||
@@ -181,15 +199,6 @@ public abstract class AccessFlags {
|
||||
setFlag(Const.ACC_VOLATILE, flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setAccessFlags(final int accessFlags) {
|
||||
this.access_flags = accessFlags;
|
||||
}
|
||||
|
||||
private void setFlag(final int flag, final boolean set) {
|
||||
if ((access_flags & flag) != 0) { // Flag is set already
|
||||
if (!set) {
|
||||
@@ -199,13 +208,4 @@ public abstract class AccessFlags {
|
||||
access_flags |= flag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set access flags aka "modifiers".
|
||||
*
|
||||
* @param accessFlags Access flags of the object.
|
||||
*/
|
||||
public final void setModifiers(final int accessFlags) {
|
||||
setAccessFlags(accessFlags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@ public class AnnotationDefault extends Attribute {
|
||||
private ElementValue defaultValue;
|
||||
|
||||
/**
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
AnnotationDefault(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||
@@ -44,8 +44,8 @@ public class AnnotationDefault extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param defaultValue the annotation's default value
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
|
||||
@@ -31,11 +31,21 @@ import java.util.stream.Stream;
|
||||
public class AnnotationEntry implements Node {
|
||||
|
||||
public static final AnnotationEntry[] EMPTY_ARRAY = {};
|
||||
private final int typeIndex;
|
||||
private final ConstantPool constantPool;
|
||||
private final boolean isRuntimeVisible;
|
||||
private List<ElementValuePair> elementValuePairs;
|
||||
|
||||
public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
this.typeIndex = typeIndex;
|
||||
this.constantPool = constantPool;
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
}
|
||||
|
||||
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
|
||||
// Find attributes that contain annotation data
|
||||
return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
|
||||
.toArray(AnnotationEntry[]::new);
|
||||
.toArray(AnnotationEntry[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,25 +63,11 @@ public class AnnotationEntry implements Node {
|
||||
annotationEntry.elementValuePairs = new ArrayList<>();
|
||||
for (int i = 0; i < numElementValuePairs; i++) {
|
||||
annotationEntry.elementValuePairs
|
||||
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
||||
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
||||
}
|
||||
return annotationEntry;
|
||||
}
|
||||
|
||||
private final int typeIndex;
|
||||
|
||||
private final ConstantPool constantPool;
|
||||
|
||||
private final boolean isRuntimeVisible;
|
||||
|
||||
private List<ElementValuePair> elementValuePairs;
|
||||
|
||||
public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
this.typeIndex = typeIndex;
|
||||
this.constantPool = constantPool;
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
||||
@@ -31,8 +31,8 @@ import java.util.stream.Stream;
|
||||
*/
|
||||
public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> {
|
||||
|
||||
private AnnotationEntry[] annotationTable;
|
||||
private final boolean isRuntimeVisible;
|
||||
private AnnotationEntry[] annotationTable;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
@@ -45,7 +45,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
* @param isRuntimeVisible whether this Annotation visible at runtime
|
||||
*/
|
||||
public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
|
||||
final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
final ConstantPool constantPool, final boolean isRuntimeVisible) {
|
||||
super(annotationType, nameIndex, length, constantPool);
|
||||
this.annotationTable = annotationTable;
|
||||
this.isRuntimeVisible = isRuntimeVisible;
|
||||
@@ -63,7 +63,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
|
||||
final boolean isRuntimeVisible) throws IOException {
|
||||
final boolean isRuntimeVisible) throws IOException {
|
||||
this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
|
||||
final int annotationTableLength = input.readUnsignedShort();
|
||||
annotationTable = new AnnotationEntry[annotationTableLength];
|
||||
|
||||
@@ -53,22 +53,63 @@ import java.util.Map;
|
||||
*/
|
||||
public abstract class Attribute implements Cloneable, Node {
|
||||
|
||||
private static final boolean debug = Boolean.getBoolean(Attribute.class.getCanonicalName() + ".debug"); // Debugging on/off
|
||||
|
||||
private static final Map<String, Object> READERS = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final Attribute[] EMPTY_ARRAY = {};
|
||||
private static final boolean debug = Boolean.getBoolean(Attribute.class.getCanonicalName() + ".debug"); // Debugging on/off
|
||||
private static final Map<String, Object> READERS = new HashMap<>();
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int name_index; // Points to attribute name in constant pool TODO make private (has getter & setter)
|
||||
/**
|
||||
* @deprecated (since 6.0) (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int length; // Content length of attribute field TODO make private (has getter & setter)
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // Tag to distinguish subclasses TODO make private & final; supposed to be immutable
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool constant_pool; // TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* <pre>
|
||||
* attribute_info {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u1 info[attribute_length];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param tag tag.
|
||||
* @param nameIndex u2 name index.
|
||||
* @param length u4 length.
|
||||
* @param constantPool constant pool.
|
||||
*/
|
||||
protected Attribute(final byte tag, final int nameIndex, final int length, final ConstantPool constantPool) {
|
||||
this.tag = tag;
|
||||
this.name_index = Args.requireU2(nameIndex, 0, constantPool.getLength(), getClass().getSimpleName() + " name index");
|
||||
this.length = Args.requireU4(length, getClass().getSimpleName() + " attribute length");
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an Attribute reader capable of parsing (user-defined) attributes named "name". You should not add readers for the
|
||||
* standard attributes such as "LineNumberTable", because those are handled internally.
|
||||
*
|
||||
* @param name the name of the attribute as stored in the class file
|
||||
* @param name the name of the attribute as stored in the class file
|
||||
* @param unknownAttributeReader the reader object
|
||||
*/
|
||||
public static void addAttributeReader(final String name, final UnknownAttributeReader unknownAttributeReader) {
|
||||
@@ -85,13 +126,12 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
* Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It
|
||||
* is called by the Field and Method constructor methods.
|
||||
*
|
||||
* @see JavaField
|
||||
* @see JavaMethod
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @param dataInput Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @return Attribute
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see JavaField
|
||||
* @see JavaMethod
|
||||
* @since 6.0
|
||||
*/
|
||||
public static Attribute readAttribute(final DataInput dataInput, final ConstantPool constantPool) throws IOException {
|
||||
@@ -113,74 +153,74 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
|
||||
// Call proper constructor, depending on 'tag'
|
||||
switch (tag) {
|
||||
case Const.ATTR_UNKNOWN:
|
||||
final Object r = READERS.get(name);
|
||||
if (r instanceof UnknownAttributeReader) {
|
||||
return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool);
|
||||
}
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CONSTANT_VALUE:
|
||||
return new ConstantValue(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SOURCE_FILE:
|
||||
return new SourceFile(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CODE:
|
||||
return new Code(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_EXCEPTIONS:
|
||||
return new ExceptionTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LINE_NUMBER_TABLE:
|
||||
return new LineNumberTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
||||
return new LocalVariableTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_INNER_CLASSES:
|
||||
return new InnerClasses(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SYNTHETIC:
|
||||
return new Synthetic(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_DEPRECATED:
|
||||
return new Deprecated(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_PMG:
|
||||
return new PMGClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SIGNATURE:
|
||||
return new Signature(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP:
|
||||
// old style stack map: unneeded for JDK5 and below;
|
||||
// illegal(?) for JDK6 and above. So just delete with a warning.
|
||||
println("Warning: Obsolete StackMap attribute ignored.");
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
||||
return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
||||
return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ANNOTATION_DEFAULT:
|
||||
return new AnnotationDefault(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
||||
return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ENCLOSING_METHOD:
|
||||
return new EnclosingMethod(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP_TABLE:
|
||||
// read new style stack map: StackMapTable. The rest of the code
|
||||
// calls this a StackMap for historical reasons.
|
||||
return new StackMap(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_BOOTSTRAP_METHODS:
|
||||
return new BootstrapMethods(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_METHOD_PARAMETERS:
|
||||
return new MethodParameters(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE:
|
||||
return new Module(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_PACKAGES:
|
||||
return new ModulePackages(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_MAIN_CLASS:
|
||||
return new ModuleMainClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_HOST:
|
||||
return new NestHost(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_MEMBERS:
|
||||
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
||||
default:
|
||||
// Never reached
|
||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
||||
case Const.ATTR_UNKNOWN:
|
||||
final Object r = READERS.get(name);
|
||||
if (r instanceof UnknownAttributeReader) {
|
||||
return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool);
|
||||
}
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CONSTANT_VALUE:
|
||||
return new ConstantValue(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SOURCE_FILE:
|
||||
return new SourceFile(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_CODE:
|
||||
return new Code(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_EXCEPTIONS:
|
||||
return new ExceptionTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LINE_NUMBER_TABLE:
|
||||
return new LineNumberTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
||||
return new LocalVariableTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_INNER_CLASSES:
|
||||
return new InnerClasses(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SYNTHETIC:
|
||||
return new Synthetic(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_DEPRECATED:
|
||||
return new Deprecated(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_PMG:
|
||||
return new PMGClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_SIGNATURE:
|
||||
return new Signature(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP:
|
||||
// old style stack map: unneeded for JDK5 and below;
|
||||
// illegal(?) for JDK6 and above. So just delete with a warning.
|
||||
println("Warning: Obsolete StackMap attribute ignored.");
|
||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
||||
return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
||||
return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
||||
return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ANNOTATION_DEFAULT:
|
||||
return new AnnotationDefault(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
||||
return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_ENCLOSING_METHOD:
|
||||
return new EnclosingMethod(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_STACK_MAP_TABLE:
|
||||
// read new style stack map: StackMapTable. The rest of the code
|
||||
// calls this a StackMap for historical reasons.
|
||||
return new StackMap(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_BOOTSTRAP_METHODS:
|
||||
return new BootstrapMethods(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_METHOD_PARAMETERS:
|
||||
return new MethodParameters(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE:
|
||||
return new Module(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_PACKAGES:
|
||||
return new ModulePackages(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_MODULE_MAIN_CLASS:
|
||||
return new ModuleMainClass(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_HOST:
|
||||
return new NestHost(nameIndex, length, dataInput, constantPool);
|
||||
case Const.ATTR_NEST_MEMBERS:
|
||||
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
||||
default:
|
||||
// Never reached
|
||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,13 +228,12 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
* Class method reads one attribute from the input data stream. This method must not be accessible from the outside. It
|
||||
* is called by the Field and Method constructor methods.
|
||||
*
|
||||
* @see JavaField
|
||||
* @see JavaMethod
|
||||
*
|
||||
* @param dataInputStream Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
* @return Attribute
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @see JavaField
|
||||
* @see JavaMethod
|
||||
*/
|
||||
public static Attribute readAttribute(final DataInputStream dataInputStream, final ConstantPool constantPool) throws IOException {
|
||||
return readAttribute((DataInput) dataInputStream, constantPool);
|
||||
@@ -209,53 +248,6 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
READERS.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int name_index; // Points to attribute name in constant pool TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int length; // Content length of attribute field TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // Tag to distinguish subclasses TODO make private & final; supposed to be immutable
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool constant_pool; // TODO make private (has getter & setter)
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
*
|
||||
* <pre>
|
||||
* attribute_info {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
* u1 info[attribute_length];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param tag tag.
|
||||
* @param nameIndex u2 name index.
|
||||
* @param length u4 length.
|
||||
* @param constantPool constant pool.
|
||||
*/
|
||||
protected Attribute(final byte tag, final int nameIndex, final int length, final ConstantPool constantPool) {
|
||||
this.tag = tag;
|
||||
this.name_index = Args.requireU2(nameIndex, 0, constantPool.getLength(), getClass().getSimpleName() + " name index");
|
||||
this.length = Args.requireU4(length, getClass().getSimpleName() + " attribute length");
|
||||
this.constant_pool = 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.
|
||||
@@ -306,6 +298,14 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
return constant_pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
* @see ConstantPool
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Length of attribute field in bytes.
|
||||
*/
|
||||
@@ -313,6 +313,13 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length length in bytes.
|
||||
*/
|
||||
public final void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of attribute
|
||||
* @since 6.0
|
||||
@@ -328,28 +335,6 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
return name_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method.
|
||||
*/
|
||||
public final byte getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
* @see ConstantPool
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length length in bytes.
|
||||
*/
|
||||
public final void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex of attribute.
|
||||
*/
|
||||
@@ -357,6 +342,13 @@ public abstract class Attribute implements Cloneable, Node {
|
||||
this.name_index = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Tag of attribute, i.e., its type. Value may not be altered, thus there is no setTag() method.
|
||||
*/
|
||||
public final byte getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return attribute name.
|
||||
*/
|
||||
|
||||
@@ -29,15 +29,19 @@ import java.util.Arrays;
|
||||
* and an array of the bootstrap arguments.
|
||||
*
|
||||
* @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>
|
||||
* The BootstrapMethods Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class BootstrapMethod implements Cloneable {
|
||||
|
||||
/** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */
|
||||
/**
|
||||
* Index of the CONSTANT_MethodHandle_info structure in the constant_pool table
|
||||
*/
|
||||
private int bootstrapMethodRef;
|
||||
|
||||
/** Array of references to the constant_pool table */
|
||||
/**
|
||||
* Array of references to the constant_pool table
|
||||
*/
|
||||
private int[] bootstrapArguments;
|
||||
|
||||
/**
|
||||
@@ -110,20 +114,6 @@ public class BootstrapMethod implements Cloneable {
|
||||
return bootstrapArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index into constant_pool of bootstrap_method
|
||||
*/
|
||||
public int getBootstrapMethodRef() {
|
||||
return bootstrapMethodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count of number of boostrap arguments
|
||||
*/
|
||||
public int getNumBootstrapArguments() {
|
||||
return bootstrapArguments.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info
|
||||
*/
|
||||
@@ -131,6 +121,13 @@ public class BootstrapMethod implements Cloneable {
|
||||
this.bootstrapArguments = bootstrapArguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index into constant_pool of bootstrap_method
|
||||
*/
|
||||
public int getBootstrapMethodRef() {
|
||||
return bootstrapMethodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle
|
||||
*/
|
||||
@@ -138,6 +135,13 @@ public class BootstrapMethod implements Cloneable {
|
||||
this.bootstrapMethodRef = bootstrapMethodRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return count of number of boostrap arguments
|
||||
*/
|
||||
public int getNumBootstrapArguments() {
|
||||
return bootstrapArguments.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.stream.Stream;
|
||||
* This class represents a BootstrapMethods attribute.
|
||||
*
|
||||
* @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>
|
||||
* The BootstrapMethods Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class BootstrapMethods extends Attribute implements Iterable<BootstrapMethod> {
|
||||
@@ -47,10 +47,10 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param bootstrapMethods array of bootstrap methods
|
||||
* @param constantPool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, constantPool);
|
||||
@@ -60,9 +60,9 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
/**
|
||||
* Construct object from Input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@@ -122,11 +122,6 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
return bootstrapMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BootstrapMethod> iterator() {
|
||||
return Stream.of(bootstrapMethods).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bootstrapMethods the array of bootstrap methods
|
||||
*/
|
||||
@@ -134,6 +129,11 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
||||
this.bootstrapMethods = bootstrapMethods;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<BootstrapMethod> iterator() {
|
||||
return Stream.of(bootstrapMethods).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.zip.ZipFile;
|
||||
* Wrapper class that parses a given Java .class file. The method <a href ="#parse">parse</a> returns a
|
||||
* <a href ="JavaClass.html"> JavaClass</a> object on success. When an I/O error or an inconsistency occurs an
|
||||
* appropriate exception is propagated back to the caller.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* the structure of a bytecode file.
|
||||
@@ -34,9 +34,10 @@ import java.util.zip.ZipFile;
|
||||
public final class ClassParser {
|
||||
|
||||
private static final int BUFSIZE = 8192;
|
||||
private DataInputStream dataInputStream;
|
||||
private final boolean fileOwned;
|
||||
private final String fileName;
|
||||
private final boolean isZip; // Loaded from zip file
|
||||
private DataInputStream dataInputStream;
|
||||
private String zipFile;
|
||||
private int classNameIndex;
|
||||
private int superclassNameIndex;
|
||||
@@ -48,13 +49,12 @@ public final class ClassParser {
|
||||
private JavaField[] fields; // class fields, i.e., its variables
|
||||
private JavaMethod[] methods; // methods defined in the class
|
||||
private Attribute[] attributes; // attributes defined in the class
|
||||
private final boolean isZip; // Loaded from zip file
|
||||
|
||||
/**
|
||||
* Parses class from the given stream.
|
||||
*
|
||||
* @param inputStream Input stream
|
||||
* @param fileName File name
|
||||
* @param fileName File name
|
||||
*/
|
||||
public ClassParser(final InputStream inputStream, final String fileName) {
|
||||
this.fileName = fileName;
|
||||
@@ -82,7 +82,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) {
|
||||
@@ -98,7 +98,7 @@ public final class ClassParser {
|
||||
* 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.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
public JavaClass parse() throws IOException, ClassFormatException {
|
||||
@@ -172,13 +172,13 @@ public final class ClassParser {
|
||||
}
|
||||
// Return the information we have gathered in a new object
|
||||
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, accessFlags, constantPool, interfaces, fields, methods, attributes,
|
||||
isZip ? JavaClass.ZIP : JavaClass.FILE);
|
||||
isZip ? JavaClass.ZIP : JavaClass.FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads information about the attributes of the class.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readAttributes() throws IOException, ClassFormatException {
|
||||
@@ -192,7 +192,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads information about the class and its super class.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readClassInfo() throws IOException, ClassFormatException {
|
||||
@@ -213,7 +213,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads constant pool entries.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readConstantPool() throws IOException, ClassFormatException {
|
||||
@@ -223,7 +223,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads information about the fields of the class, i.e., its variables.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readFields() throws IOException, ClassFormatException {
|
||||
@@ -238,7 +238,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Checks whether the header of the file is ok. Of course, this has to be the first action on successive file reads.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readID() throws IOException, ClassFormatException {
|
||||
@@ -250,7 +250,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads information about the interfaces implemented by this class.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readInterfaces() throws IOException, ClassFormatException {
|
||||
@@ -264,7 +264,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads information about the methods of the class.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readMethods() throws IOException {
|
||||
@@ -278,7 +278,7 @@ public final class ClassParser {
|
||||
/**
|
||||
* Reads major and minor version of compiler which created the file.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
private void readVersion() throws IOException, ClassFormatException {
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.Arrays;
|
||||
* This class represents a chunk of Java byte code contained in a method. It is instantiated by the
|
||||
* <em>Attribute.readAttribute()</em> method. A <em>Code</em> attribute contains informations about operand stack, local
|
||||
* variables, byte code and the exceptions handled within this method.
|
||||
*
|
||||
* <p>
|
||||
* This attribute has attributes itself, namely <em>LineNumberTable</em> which is used for debugging purposes and
|
||||
* <em>LocalVariableTable</em> which contains information about the local variables.
|
||||
*
|
||||
@@ -52,6 +52,7 @@ import java.util.Arrays;
|
||||
* attribute_info attributes[attributes_count];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see Attribute
|
||||
* @see CodeException
|
||||
* @see LineNumberTable
|
||||
@@ -77,9 +78,9 @@ public final class Code extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param file Input stream
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param file Input stream
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
Code(final int nameIndex, final int length, final DataInput file, final ConstantPool constantPool) throws IOException {
|
||||
@@ -113,17 +114,17 @@ public final class Code extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param maxStack Maximum size of stack
|
||||
* @param maxLocals Number of local variables
|
||||
* @param code Actual byte code
|
||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||
* @param length Content length in bytes
|
||||
* @param maxStack Maximum size of stack
|
||||
* @param maxLocals Number of local variables
|
||||
* @param code Actual byte code
|
||||
* @param exceptionTable of handled exceptions
|
||||
* @param attributes Attributes of code: LineNumber or LocalVariable
|
||||
* @param constantPool Array of constants
|
||||
* @param attributes Attributes of code: LineNumber or LocalVariable
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Code(final int nameIndex, final int length, final int maxStack, final int maxLocals, final byte[] code, final CodeException[] exceptionTable,
|
||||
final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_CODE, nameIndex, length, constantPool);
|
||||
this.maxStack = Args.requireU2(maxStack, "maxStack");
|
||||
this.maxLocals = Args.requireU2(maxLocals, "maxLocals");
|
||||
@@ -147,7 +148,7 @@ public final class Code extends Attribute {
|
||||
|
||||
/**
|
||||
* @return the full size of this code attribute, minus its first 6 bytes, including the size of all its contained
|
||||
* attributes
|
||||
* attributes
|
||||
*/
|
||||
private int calculateLength() {
|
||||
int len = 0;
|
||||
@@ -160,9 +161,8 @@ public final class Code extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return deep copy of this attribute
|
||||
*
|
||||
* @param constantPool the constant pool to duplicate
|
||||
* @return deep copy of this attribute
|
||||
*/
|
||||
@Override
|
||||
public Attribute copy(final ConstantPool constantPool) {
|
||||
@@ -209,6 +209,14 @@ public final class Code extends Attribute {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set for this Code
|
||||
*/
|
||||
public void setAttributes(final Attribute[] attributes) {
|
||||
this.attributes = attributes != null ? attributes : EMPTY_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Actual byte code of the method.
|
||||
*/
|
||||
@@ -216,6 +224,14 @@ public final class Code extends Attribute {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code byte code
|
||||
*/
|
||||
public void setCode(final byte[] code) {
|
||||
this.code = code != null ? code : ArrayUtils.EMPTY_BYTE_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Table of handled exceptions.
|
||||
* @see CodeException
|
||||
@@ -224,15 +240,23 @@ public final class Code extends Attribute {
|
||||
return exceptionTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionTable exception table
|
||||
*/
|
||||
public void setExceptionTable(final CodeException[] exceptionTable) {
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the internal length of this code attribute (minus the first 6 bytes) and excluding all its attributes
|
||||
*/
|
||||
private int getInternalLength() {
|
||||
return 2 /* maxStack */ + 2 /* maxLocals */ + 4 /* code length */
|
||||
+ code.length /* byte-code */
|
||||
+ 2 /* exception-table length */
|
||||
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
||||
+ 2 /* attributes count */;
|
||||
+ code.length /* byte-code */
|
||||
+ 2 /* exception-table length */
|
||||
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
||||
+ 2 /* attributes count */;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,37 +290,6 @@ public final class Code extends Attribute {
|
||||
return maxLocals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum size of stack used by this method.
|
||||
*/
|
||||
public int getMaxStack() {
|
||||
return maxStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param attributes the attributes to set for this Code
|
||||
*/
|
||||
public void setAttributes(final Attribute[] attributes) {
|
||||
this.attributes = attributes != null ? attributes : EMPTY_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @param code byte code
|
||||
*/
|
||||
public void setCode(final byte[] code) {
|
||||
this.code = code != null ? code : ArrayUtils.EMPTY_BYTE_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionTable exception table
|
||||
*/
|
||||
public void setExceptionTable(final CodeException[] exceptionTable) {
|
||||
this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
|
||||
super.setLength(calculateLength()); // Adjust length
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxLocals maximum number of local variables
|
||||
*/
|
||||
@@ -304,6 +297,13 @@ public final class Code extends Attribute {
|
||||
this.maxLocals = maxLocals;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Maximum size of stack used by this method.
|
||||
*/
|
||||
public int getMaxStack() {
|
||||
return maxStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxStack maximum stack size
|
||||
*/
|
||||
@@ -328,7 +328,7 @@ public final class Code extends Attribute {
|
||||
public String toString(final boolean verbose) {
|
||||
final StringBuilder buf = new StringBuilder(100); // CHECKSTYLE IGNORE MagicNumber
|
||||
buf.append("Code(maxStack = ").append(maxStack).append(", maxLocals = ").append(maxLocals).append(", code_length = ").append(code.length).append(")\n")
|
||||
.append(Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose));
|
||||
.append(Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose));
|
||||
if (exceptionTable.length > 0) {
|
||||
buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
|
||||
for (final CodeException exception : exceptionTable) {
|
||||
|
||||
@@ -154,27 +154,6 @@ public final class CodeException implements Cloneable, Node {
|
||||
return catchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exclusive end index of the region where the handler is active.
|
||||
*/
|
||||
public int getEndPC() {
|
||||
return endPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Starting address of exception handler, relative to the code.
|
||||
*/
|
||||
public int getHandlerPC() {
|
||||
return handlerPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Inclusive start index of the region where the handler is active.
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param catchType the type of exception that is caught
|
||||
*/
|
||||
@@ -182,6 +161,13 @@ public final class CodeException implements Cloneable, Node {
|
||||
this.catchType = catchType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exclusive end index of the region where the handler is active.
|
||||
*/
|
||||
public int getEndPC() {
|
||||
return endPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endPc end of handled block
|
||||
*/
|
||||
@@ -189,6 +175,13 @@ public final class CodeException implements Cloneable, Node {
|
||||
this.endPc = endPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Starting address of exception handler, relative to the code.
|
||||
*/
|
||||
public int getHandlerPC() {
|
||||
return handlerPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param handlerPc where the actual code is
|
||||
*/
|
||||
@@ -196,6 +189,13 @@ public final class CodeException implements Cloneable, Node {
|
||||
this.handlerPc = handlerPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Inclusive start index of the region where the handler is active.
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc start of handled block
|
||||
*/
|
||||
|
||||
@@ -45,6 +45,15 @@ public abstract class Constant implements Cloneable, Node {
|
||||
return THIS.toString().hashCode();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // TODO should be private & final
|
||||
|
||||
Constant(final byte tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
@@ -53,64 +62,6 @@ public abstract class Constant implements Cloneable, Node {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads one constant from the given input, the type depends on a tag byte.
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @return Constant object
|
||||
* @throws IOException if an I/O error occurs reading from the given {@code dataInput}.
|
||||
* @throws ClassFormatException if the next byte is not recognized
|
||||
* @since 6.0 made public
|
||||
*/
|
||||
public static Constant readConstant(final DataInput dataInput) throws IOException, ClassFormatException {
|
||||
final byte b = dataInput.readByte(); // Read tag byte
|
||||
switch (b) {
|
||||
case Const.CONSTANT_Class:
|
||||
return new ConstantClass(dataInput);
|
||||
case Const.CONSTANT_Fieldref:
|
||||
return new ConstantFieldref(dataInput);
|
||||
case Const.CONSTANT_Methodref:
|
||||
return new ConstantMethodref(dataInput);
|
||||
case Const.CONSTANT_InterfaceMethodref:
|
||||
return new ConstantInterfaceMethodref(dataInput);
|
||||
case Const.CONSTANT_String:
|
||||
return new ConstantString(dataInput);
|
||||
case Const.CONSTANT_Integer:
|
||||
return new ConstantInteger(dataInput);
|
||||
case Const.CONSTANT_Float:
|
||||
return new ConstantFloat(dataInput);
|
||||
case Const.CONSTANT_Long:
|
||||
return new ConstantLong(dataInput);
|
||||
case Const.CONSTANT_Double:
|
||||
return new ConstantDouble(dataInput);
|
||||
case Const.CONSTANT_NameAndType:
|
||||
return new ConstantNameAndType(dataInput);
|
||||
case Const.CONSTANT_Utf8:
|
||||
return ConstantUtf8.getInstance(dataInput);
|
||||
case Const.CONSTANT_MethodHandle:
|
||||
return new ConstantMethodHandle(dataInput);
|
||||
case Const.CONSTANT_MethodType:
|
||||
return new ConstantMethodType(dataInput);
|
||||
case Const.CONSTANT_Dynamic:
|
||||
return new ConstantDynamic(dataInput);
|
||||
case Const.CONSTANT_InvokeDynamic:
|
||||
return new ConstantInvokeDynamic(dataInput);
|
||||
case Const.CONSTANT_Module:
|
||||
return new ConstantModule(dataInput);
|
||||
case Const.CONSTANT_Package:
|
||||
return new ConstantPackage(dataInput);
|
||||
default:
|
||||
throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/*
|
||||
* In fact this tag is redundant since we can distinguish different 'Constant' objects by their type, i.e., via
|
||||
* 'instanceof'. In some places we will use the tag for switch()es anyway.
|
||||
@@ -118,14 +69,63 @@ public abstract class Constant implements Cloneable, Node {
|
||||
* First, we want match the specification as closely as possible. Second we need the tag as an index to select the
|
||||
* corresponding class name from the 'CONSTANT_NAMES' array.
|
||||
*/
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected byte tag; // TODO should be private & final
|
||||
|
||||
Constant(final byte tag) {
|
||||
this.tag = tag;
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads one constant from the given input, the type depends on a tag byte.
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @return Constant object
|
||||
* @throws IOException if an I/O error occurs reading from the given {@code dataInput}.
|
||||
* @throws ClassFormatException if the next byte is not recognized
|
||||
* @since 6.0 made public
|
||||
*/
|
||||
public static Constant readConstant(final DataInput dataInput) throws IOException, ClassFormatException {
|
||||
final byte b = dataInput.readByte(); // Read tag byte
|
||||
switch (b) {
|
||||
case Const.CONSTANT_Class:
|
||||
return new ConstantClass(dataInput);
|
||||
case Const.CONSTANT_Fieldref:
|
||||
return new ConstantFieldref(dataInput);
|
||||
case Const.CONSTANT_Methodref:
|
||||
return new ConstantMethodref(dataInput);
|
||||
case Const.CONSTANT_InterfaceMethodref:
|
||||
return new ConstantInterfaceMethodref(dataInput);
|
||||
case Const.CONSTANT_String:
|
||||
return new ConstantString(dataInput);
|
||||
case Const.CONSTANT_Integer:
|
||||
return new ConstantInteger(dataInput);
|
||||
case Const.CONSTANT_Float:
|
||||
return new ConstantFloat(dataInput);
|
||||
case Const.CONSTANT_Long:
|
||||
return new ConstantLong(dataInput);
|
||||
case Const.CONSTANT_Double:
|
||||
return new ConstantDouble(dataInput);
|
||||
case Const.CONSTANT_NameAndType:
|
||||
return new ConstantNameAndType(dataInput);
|
||||
case Const.CONSTANT_Utf8:
|
||||
return ConstantUtf8.getInstance(dataInput);
|
||||
case Const.CONSTANT_MethodHandle:
|
||||
return new ConstantMethodHandle(dataInput);
|
||||
case Const.CONSTANT_MethodType:
|
||||
return new ConstantMethodType(dataInput);
|
||||
case Const.CONSTANT_Dynamic:
|
||||
return new ConstantDynamic(dataInput);
|
||||
case Const.CONSTANT_InvokeDynamic:
|
||||
return new ConstantInvokeDynamic(dataInput);
|
||||
case Const.CONSTANT_Module:
|
||||
return new ConstantModule(dataInput);
|
||||
case Const.CONSTANT_Package:
|
||||
return new ConstantPackage(dataInput);
|
||||
default:
|
||||
throw new ClassFormatException("Invalid byte tag in constant pool: " + b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class ConstantCP extends Constant {
|
||||
/**
|
||||
* Initialize instance from file data.
|
||||
*
|
||||
* @param tag Constant type tag
|
||||
* @param tag Constant type tag
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@@ -62,7 +62,7 @@ public abstract class ConstantCP extends Constant {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classIndex Reference to the class containing the field
|
||||
* @param classIndex Reference to the class containing the field
|
||||
* @param nameAndTypeIndex and the field signature
|
||||
*/
|
||||
protected ConstantCP(final byte tag, final int classIndex, final int nameAndTypeIndex) {
|
||||
@@ -107,13 +107,6 @@ public abstract class ConstantCP extends Constant {
|
||||
return class_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reference (index) to signature of the field.
|
||||
*/
|
||||
public final int getNameAndTypeIndex() {
|
||||
return name_and_type_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classIndex points to Constant_class
|
||||
*/
|
||||
@@ -121,6 +114,13 @@ public abstract class ConstantCP extends Constant {
|
||||
this.class_index = classIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Reference (index) to signature of the field.
|
||||
*/
|
||||
public final int getNameAndTypeIndex() {
|
||||
return name_and_type_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameAndTypeIndex points to Constant_NameAndType
|
||||
*/
|
||||
@@ -130,8 +130,8 @@ public abstract class ConstantCP extends Constant {
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*
|
||||
* not final as ConstantInvokeDynamic needs to modify
|
||||
* <p>
|
||||
* not final as ConstantInvokeDynamic needs to modify
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -88,6 +88,13 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent the double value
|
||||
*/
|
||||
public void setBytes(final double bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Double object
|
||||
*/
|
||||
@@ -96,13 +103,6 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
||||
return Double.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent the double value
|
||||
*/
|
||||
public void setBytes(final double bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @see Constant
|
||||
* @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html"> Change request for JEP
|
||||
* 309</a>
|
||||
* 309</a>
|
||||
* @since 6.3
|
||||
*/
|
||||
public final class ConstantDynamic extends ConstantCP {
|
||||
@@ -68,8 +68,8 @@ public final class ConstantDynamic extends ConstantCP {
|
||||
|
||||
/**
|
||||
* @return Reference (index) to bootstrap method this constant refers to.
|
||||
*
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* <p>
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* @since 6.0
|
||||
*/
|
||||
public int getBootstrapMethodAttrIndex() {
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class ConstantFieldref extends ConstantCP {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classIndex Reference to the class containing the Field
|
||||
* @param classIndex Reference to the class containing the Field
|
||||
* @param nameAndTypeIndex and the Field signature
|
||||
*/
|
||||
public ConstantFieldref(final int classIndex, final int nameAndTypeIndex) {
|
||||
|
||||
@@ -89,6 +89,13 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this float
|
||||
*/
|
||||
public void setBytes(final float bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Float object
|
||||
*/
|
||||
@@ -97,13 +104,6 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
||||
return Float.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this float
|
||||
*/
|
||||
public void setBytes(final float bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -88,6 +88,13 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this integer
|
||||
*/
|
||||
public void setBytes(final int bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Integer object
|
||||
*/
|
||||
@@ -96,13 +103,6 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
||||
return Integer.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this integer
|
||||
*/
|
||||
public void setBytes(final int bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class ConstantInterfaceMethodref extends ConstantCP {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param nameAndTypeIndex and the method signature
|
||||
*/
|
||||
public ConstantInterfaceMethodref(final int classIndex, final int nameAndTypeIndex) {
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @see Constant
|
||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10"> The
|
||||
* CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification</a>
|
||||
* CONSTANT_InvokeDynamic_info Structure in The Java Virtual Machine Specification</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public final class ConstantInvokeDynamic extends ConstantCP {
|
||||
@@ -67,8 +67,8 @@ public final class ConstantInvokeDynamic extends ConstantCP {
|
||||
|
||||
/**
|
||||
* @return Reference (index) to bootstrap method this constant refers to.
|
||||
*
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* <p>
|
||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||
* @since 6.0
|
||||
*/
|
||||
public int getBootstrapMethodAttrIndex() {
|
||||
|
||||
@@ -88,6 +88,13 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this long
|
||||
*/
|
||||
public void setBytes(final long bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Long object
|
||||
*/
|
||||
@@ -96,13 +103,6 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
||||
return Long.valueOf(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes the raw bytes that represent this long
|
||||
*/
|
||||
public void setBytes(final long bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -86,14 +86,14 @@ public final class ConstantMethodHandle extends Constant {
|
||||
return referenceIndex;
|
||||
}
|
||||
|
||||
public int getReferenceKind() {
|
||||
return referenceKind;
|
||||
}
|
||||
|
||||
public void setReferenceIndex(final int referenceIndex) {
|
||||
this.referenceIndex = referenceIndex;
|
||||
}
|
||||
|
||||
public int getReferenceKind() {
|
||||
return referenceKind;
|
||||
}
|
||||
|
||||
public void setReferenceKind(final int referenceKind) {
|
||||
this.referenceKind = referenceKind;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public final class ConstantMethodref extends ConstantCP {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param classIndex Reference to the class containing the method
|
||||
* @param nameAndTypeIndex and the method signature
|
||||
*/
|
||||
public ConstantMethodref(final int classIndex, final int nameAndTypeIndex) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public final class ConstantNameAndType extends Constant {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Name of field/method
|
||||
* @param nameIndex Name of field/method
|
||||
* @param signatureIndex and its signature
|
||||
*/
|
||||
public ConstantNameAndType(final int nameIndex, final int signatureIndex) {
|
||||
@@ -100,6 +100,13 @@ public final class ConstantNameAndType extends Constant {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index of this constant
|
||||
*/
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return signature
|
||||
*/
|
||||
@@ -114,13 +121,6 @@ public final class ConstantNameAndType extends Constant {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex the name index of this constant
|
||||
*/
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex the signature index in the constant pool of this type
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -57,47 +57,53 @@ import java.util.Objects;
|
||||
*/
|
||||
public final class ConstantUtf8 extends Constant {
|
||||
|
||||
private static class Cache {
|
||||
|
||||
private static final boolean BCEL_STATISTICS = Boolean.getBoolean(SYS_PROP_STATISTICS);
|
||||
private static final int MAX_ENTRIES = Integer.getInteger(SYS_PROP_CACHE_MAX_ENTRIES, 0).intValue();
|
||||
private static final int INITIAL_CAPACITY = (int) (MAX_ENTRIES / 0.75);
|
||||
|
||||
private static final HashMap<String, ConstantUtf8> CACHE = new LinkedHashMap<String, ConstantUtf8>(INITIAL_CAPACITY, 0.75f, true) {
|
||||
|
||||
private static final long serialVersionUID = -8506975356158971766L;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<String, ConstantUtf8> eldest) {
|
||||
return size() > MAX_ENTRIES;
|
||||
}
|
||||
};
|
||||
|
||||
// Set the size to 0 or below to skip caching entirely
|
||||
private static final int MAX_ENTRY_SIZE = Integer.getInteger(SYS_PROP_CACHE_MAX_ENTRY_SIZE, 200).intValue();
|
||||
|
||||
static boolean isEnabled() {
|
||||
return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRIES = "bcel.maxcached";
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRY_SIZE = "bcel.maxcached.size";
|
||||
private static final String SYS_PROP_STATISTICS = "bcel.statistics";
|
||||
// TODO these should perhaps be AtomicInt?
|
||||
private static volatile int considered;
|
||||
private static volatile int created;
|
||||
private static volatile int hits;
|
||||
private static volatile int skipped;
|
||||
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRIES = "bcel.maxcached";
|
||||
private static final String SYS_PROP_CACHE_MAX_ENTRY_SIZE = "bcel.maxcached.size";
|
||||
private static final String SYS_PROP_STATISTICS = "bcel.statistics";
|
||||
|
||||
static {
|
||||
if (Cache.BCEL_STATISTICS) {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(ConstantUtf8::printStats));
|
||||
}
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Initializes from another object.
|
||||
*
|
||||
* @param constantUtf8 the value.
|
||||
*/
|
||||
public ConstantUtf8(final ConstantUtf8 constantUtf8) {
|
||||
this(constantUtf8.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes instance from file data.
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantUtf8(final DataInput dataInput) throws IOException {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
value = dataInput.readUTF();
|
||||
created++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value Data
|
||||
*/
|
||||
public ConstantUtf8(final String value) {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
this.value = Objects.requireNonNull(value, "value");
|
||||
created++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache.
|
||||
*
|
||||
@@ -175,39 +181,7 @@ public final class ConstantUtf8 extends Constant {
|
||||
System.err.printf("%s Cache hit %,d/%,d, %d skipped.%n", prefix, hits, considered, skipped);
|
||||
System.err.printf("%s Total of %,d ConstantUtf8 objects created.%n", prefix, created);
|
||||
System.err.printf("%s Configuration: %s=%,d, %s=%,d.%n", prefix, SYS_PROP_CACHE_MAX_ENTRIES, Cache.MAX_ENTRIES, SYS_PROP_CACHE_MAX_ENTRY_SIZE,
|
||||
Cache.MAX_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
private final String value;
|
||||
|
||||
/**
|
||||
* Initializes from another object.
|
||||
*
|
||||
* @param constantUtf8 the value.
|
||||
*/
|
||||
public ConstantUtf8(final ConstantUtf8 constantUtf8) {
|
||||
this(constantUtf8.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes instance from file data.
|
||||
*
|
||||
* @param dataInput Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
ConstantUtf8(final DataInput dataInput) throws IOException {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
value = dataInput.readUTF();
|
||||
created++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value Data
|
||||
*/
|
||||
public ConstantUtf8(final String value) {
|
||||
super(Const.CONSTANT_Utf8);
|
||||
this.value = Objects.requireNonNull(value, "value");
|
||||
created++;
|
||||
Cache.MAX_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,4 +230,29 @@ public final class ConstantUtf8 extends Constant {
|
||||
public String toString() {
|
||||
return super.toString() + "(\"" + Utility.replace(value, "\n", "\\n") + "\")";
|
||||
}
|
||||
|
||||
private static class Cache {
|
||||
|
||||
private static final boolean BCEL_STATISTICS = Boolean.getBoolean(SYS_PROP_STATISTICS);
|
||||
private static final int MAX_ENTRIES = Integer.getInteger(SYS_PROP_CACHE_MAX_ENTRIES, 0).intValue();
|
||||
private static final int INITIAL_CAPACITY = (int) (MAX_ENTRIES / 0.75);
|
||||
|
||||
private static final HashMap<String, ConstantUtf8> CACHE = new LinkedHashMap<String, ConstantUtf8>(INITIAL_CAPACITY, 0.75f, true) {
|
||||
|
||||
private static final long serialVersionUID = -8506975356158971766L;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(final Map.Entry<String, ConstantUtf8> eldest) {
|
||||
return size() > MAX_ENTRIES;
|
||||
}
|
||||
};
|
||||
|
||||
// Set the size to 0 or below to skip caching entirely
|
||||
private static final int MAX_ENTRY_SIZE = Integer.getInteger(SYS_PROP_CACHE_MAX_ENTRY_SIZE, 200).intValue();
|
||||
|
||||
static boolean isEnabled() {
|
||||
return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.io.IOException;
|
||||
* u2 constantvalue_index;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see Attribute
|
||||
*/
|
||||
public final class ConstantValue extends Attribute {
|
||||
@@ -53,9 +54,9 @@ public final class ConstantValue extends Attribute {
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Name 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.
|
||||
*/
|
||||
@@ -64,10 +65,10 @@ public final class ConstantValue extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Name index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param constantValueIndex Index in constant pool
|
||||
* @param constantPool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ConstantValue(final int nameIndex, final int length, final int constantValueIndex, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_CONSTANT_VALUE, nameIndex, Args.require(length, 2, "ConstantValue attribute length"), constantPool);
|
||||
@@ -131,25 +132,25 @@ public final class ConstantValue extends Attribute {
|
||||
int i;
|
||||
// Print constant to string depending on its type
|
||||
switch (c.getTag()) {
|
||||
case Const.CONSTANT_Long:
|
||||
buf = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = super.getConstantPool().getConstantUtf8(i);
|
||||
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
||||
case Const.CONSTANT_Long:
|
||||
buf = String.valueOf(((ConstantLong) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Float:
|
||||
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Double:
|
||||
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_Integer:
|
||||
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
||||
break;
|
||||
case Const.CONSTANT_String:
|
||||
i = ((ConstantString) c).getStringIndex();
|
||||
c = super.getConstantPool().getConstantUtf8(i);
|
||||
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ public final class Deprecated extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param bytes Attribute contents
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param bytes Attribute contents
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public Deprecated(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||
@@ -57,9 +57,9 @@ public final class Deprecated extends Attribute {
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
|
||||
@@ -32,7 +32,7 @@ public class DescendingVisitor implements Visitor {
|
||||
private final Stack<Object> stack = new Stack<>();
|
||||
|
||||
/**
|
||||
* @param clazz Class to traverse
|
||||
* @param clazz Class to traverse
|
||||
* @param visitor visitor object to apply to all components
|
||||
*/
|
||||
public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
|
||||
@@ -153,7 +153,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.3 */
|
||||
/**
|
||||
* @since 6.3
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantDynamic(final ConstantDynamic obj) {
|
||||
stack.push(obj);
|
||||
@@ -206,7 +208,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
|
||||
stack.push(obj);
|
||||
@@ -221,7 +225,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantMethodType(final ConstantMethodType obj) {
|
||||
stack.push(obj);
|
||||
@@ -229,7 +235,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.1 */
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantModule(final ConstantModule obj) {
|
||||
stack.push(obj);
|
||||
@@ -244,7 +252,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.1 */
|
||||
/**
|
||||
* @since 6.1
|
||||
*/
|
||||
@Override
|
||||
public void visitConstantPackage(final ConstantPackage obj) {
|
||||
stack.push(obj);
|
||||
@@ -408,7 +418,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModule(final Module obj) {
|
||||
stack.push(obj);
|
||||
@@ -420,7 +432,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleExports(final ModuleExports obj) {
|
||||
stack.push(obj);
|
||||
@@ -428,7 +442,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
stack.push(obj);
|
||||
@@ -436,7 +452,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleOpens(final ModuleOpens obj) {
|
||||
stack.push(obj);
|
||||
@@ -444,7 +462,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModulePackages(final ModulePackages obj) {
|
||||
stack.push(obj);
|
||||
@@ -452,7 +472,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
stack.push(obj);
|
||||
@@ -460,7 +482,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
stack.push(obj);
|
||||
@@ -468,7 +492,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitNestHost(final NestHost obj) {
|
||||
stack.push(obj);
|
||||
@@ -476,7 +502,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitNestMembers(final NestMembers obj) {
|
||||
stack.push(obj);
|
||||
@@ -494,7 +522,9 @@ public class DescendingVisitor implements Visitor {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
@Override
|
||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
|
||||
stack.push(obj);
|
||||
|
||||
@@ -44,8 +44,9 @@ import java.io.IOException;
|
||||
* element_value values[num_values];
|
||||
* } array_value;
|
||||
* } value;
|
||||
*}
|
||||
*</pre>
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public abstract class ElementValue {
|
||||
@@ -63,72 +64,6 @@ 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';
|
||||
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException {
|
||||
return readElementValue(input, cpool, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @param arrayNesting level of current array nesting.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @since 6.7.0
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool, int arrayNesting)
|
||||
throws IOException {
|
||||
final byte tag = input.readByte();
|
||||
switch (tag) {
|
||||
case PRIMITIVE_BYTE:
|
||||
case PRIMITIVE_CHAR:
|
||||
case PRIMITIVE_DOUBLE:
|
||||
case PRIMITIVE_FLOAT:
|
||||
case PRIMITIVE_INT:
|
||||
case PRIMITIVE_LONG:
|
||||
case PRIMITIVE_SHORT:
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
case STRING:
|
||||
return new SimpleElementValue(tag, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ENUM_CONSTANT:
|
||||
return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool);
|
||||
|
||||
case CLASS:
|
||||
return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ANNOTATION:
|
||||
// TODO isRuntimeVisible
|
||||
return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool);
|
||||
|
||||
case ARRAY:
|
||||
arrayNesting++;
|
||||
if (arrayNesting > Const.MAX_ARRAY_DIMENSIONS) {
|
||||
// JVM spec 4.4.1
|
||||
throw new ClassFormatException(String.format("Arrays are only valid if they represent %,d or fewer dimensions.", Const.MAX_ARRAY_DIMENSIONS));
|
||||
}
|
||||
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);
|
||||
}
|
||||
return new ArrayElementValue(ARRAY, evalues, cpool);
|
||||
|
||||
default:
|
||||
throw new ClassFormatException("Unexpected element value tag in annotation: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
||||
*/
|
||||
@@ -145,9 +80,76 @@ public abstract class ElementValue {
|
||||
this.cpool = cpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool) throws IOException {
|
||||
return readElementValue(input, cpool, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an {@code element_value} as an {@code ElementValue}.
|
||||
*
|
||||
* @param input Raw data input.
|
||||
* @param cpool Constant pool.
|
||||
* @param arrayNesting level of current array nesting.
|
||||
* @return a new ElementValue.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @since 6.7.0
|
||||
*/
|
||||
public static ElementValue readElementValue(final DataInput input, final ConstantPool cpool, int arrayNesting)
|
||||
throws IOException {
|
||||
final byte tag = input.readByte();
|
||||
switch (tag) {
|
||||
case PRIMITIVE_BYTE:
|
||||
case PRIMITIVE_CHAR:
|
||||
case PRIMITIVE_DOUBLE:
|
||||
case PRIMITIVE_FLOAT:
|
||||
case PRIMITIVE_INT:
|
||||
case PRIMITIVE_LONG:
|
||||
case PRIMITIVE_SHORT:
|
||||
case PRIMITIVE_BOOLEAN:
|
||||
case STRING:
|
||||
return new SimpleElementValue(tag, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ENUM_CONSTANT:
|
||||
return new EnumElementValue(ENUM_CONSTANT, input.readUnsignedShort(), input.readUnsignedShort(), cpool);
|
||||
|
||||
case CLASS:
|
||||
return new ClassElementValue(CLASS, input.readUnsignedShort(), cpool);
|
||||
|
||||
case ANNOTATION:
|
||||
// TODO isRuntimeVisible
|
||||
return new AnnotationElementValue(ANNOTATION, AnnotationEntry.read(input, cpool, false), cpool);
|
||||
|
||||
case ARRAY:
|
||||
arrayNesting++;
|
||||
if (arrayNesting > Const.MAX_ARRAY_DIMENSIONS) {
|
||||
// JVM spec 4.4.1
|
||||
throw new ClassFormatException(String.format("Arrays are only valid if they represent %,d or fewer dimensions.", Const.MAX_ARRAY_DIMENSIONS));
|
||||
}
|
||||
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);
|
||||
}
|
||||
return new ArrayElementValue(ARRAY, evalues, cpool);
|
||||
|
||||
default:
|
||||
throw new ClassFormatException("Unexpected element value tag in annotation: " + tag);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void dump(DataOutputStream dos) throws IOException;
|
||||
|
||||
/** @since 6.0 */
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
final ConstantPool getConstantPool() {
|
||||
return cpool;
|
||||
}
|
||||
@@ -156,7 +158,9 @@ public abstract class ElementValue {
|
||||
return type;
|
||||
}
|
||||
|
||||
/** @since 6.0 */
|
||||
/**
|
||||
* @since 6.0
|
||||
*/
|
||||
final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -235,47 +235,65 @@ public class EmptyVisitor implements Visitor {
|
||||
public void visitMethodParameters(final MethodParameters obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModule(final Module obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleExports(final ModuleExports obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleOpens(final ModuleOpens obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModulePackages(final ModulePackages obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleProvides(final ModuleProvides obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitModuleRequires(final ModuleRequires obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitNestHost(final NestHost obj) {
|
||||
}
|
||||
|
||||
/** @since 6.4.0 */
|
||||
/**
|
||||
* @since 6.4.0
|
||||
*/
|
||||
@Override
|
||||
public void visitNestMembers(final NestMembers obj) {
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 haidnor.jvm.bcel.classfile;
|
||||
|
||||
@@ -81,6 +81,10 @@ public class EnclosingMethod extends Attribute {
|
||||
return classIndex;
|
||||
}
|
||||
|
||||
public final void setEnclosingClassIndex(final int idx) {
|
||||
classIndex = idx;
|
||||
}
|
||||
|
||||
public final ConstantNameAndType getEnclosingMethod() {
|
||||
if (methodIndex == 0) {
|
||||
return null;
|
||||
@@ -92,10 +96,6 @@ public class EnclosingMethod extends Attribute {
|
||||
return methodIndex;
|
||||
}
|
||||
|
||||
public final void setEnclosingClassIndex(final int idx) {
|
||||
classIndex = idx;
|
||||
}
|
||||
|
||||
public final void setEnclosingMethodIndex(final int idx) {
|
||||
methodIndex = idx;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.Arrays;
|
||||
* u2 exception_index_table[number_of_exceptions];
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see Code
|
||||
*/
|
||||
public final class ExceptionTable extends Attribute {
|
||||
@@ -59,9 +60,9 @@ public final class ExceptionTable extends Attribute {
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input 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.
|
||||
*/
|
||||
@@ -75,10 +76,10 @@ public final class ExceptionTable extends Attribute {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param exceptionIndexTable Table of indices in constant pool
|
||||
* @param constantPool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
|
||||
@@ -132,6 +133,14 @@ public final class ExceptionTable extends Attribute {
|
||||
return exceptionIndexTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionIndexTable the list of exception indexes Also redefines number_of_exceptions according to table
|
||||
* length.
|
||||
*/
|
||||
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : ArrayUtils.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class names of thrown exceptions
|
||||
*/
|
||||
@@ -148,14 +157,6 @@ public final class ExceptionTable extends Attribute {
|
||||
return exceptionIndexTable == null ? 0 : exceptionIndexTable.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exceptionIndexTable the list of exception indexes Also redefines number_of_exceptions according to table
|
||||
* length.
|
||||
*/
|
||||
public void setExceptionIndexTable(final int[] exceptionIndexTable) {
|
||||
this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : ArrayUtils.EMPTY_INT_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation, i.e., a list of thrown exceptions.
|
||||
*/
|
||||
|
||||
@@ -50,16 +50,13 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected int attributes_count; // No. of attributes
|
||||
|
||||
// @since 6.0
|
||||
private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
|
||||
|
||||
/**
|
||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
protected ConstantPool constant_pool;
|
||||
|
||||
// @since 6.0
|
||||
private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
|
||||
private String signatureAttributeString;
|
||||
private boolean searchedForSignatureAttribute;
|
||||
|
||||
@@ -105,14 +102,14 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
|
||||
final ConstantPool constantPool) {
|
||||
final ConstantPool constantPool) {
|
||||
super(accessFlags);
|
||||
this.name_index = nameIndex;
|
||||
this.signature_index = signatureIndex;
|
||||
@@ -173,6 +170,14 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
return attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Constant pool used by this object.
|
||||
*/
|
||||
@@ -180,6 +185,13 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
return constant_pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hunts for a signature attribute on the member and returns its contents. So where the 'regular' signature may be
|
||||
* (Ljava/util/Vector;)V the signature attribute may in fact say 'Ljava/lang/Vector<Ljava/lang/String>;' Coded for
|
||||
@@ -215,6 +227,13 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
return name_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool of object's name.
|
||||
*/
|
||||
public final void setNameIndex(final int nameIndex) {
|
||||
this.name_index = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation of object's type signature (java style)
|
||||
*/
|
||||
@@ -229,28 +248,6 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
||||
return signature_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public final void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constant_pool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool of object's name.
|
||||
*/
|
||||
public final void setNameIndex(final int nameIndex) {
|
||||
this.name_index = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex Index in constant pool of field signature.
|
||||
*/
|
||||
|
||||
@@ -55,9 +55,9 @@ public final class InnerClass implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerClassIndex Class index in constant pool of inner class
|
||||
* @param outerClassIndex Class index in constant pool of outer class
|
||||
* @param innerNameIndex Name index in constant pool of inner class
|
||||
* @param innerClassIndex Class index in constant pool of inner class
|
||||
* @param outerClassIndex Class index in constant pool of outer class
|
||||
* @param innerNameIndex Name index in constant pool of inner class
|
||||
* @param innerAccessFlags Access flags of inner class
|
||||
*/
|
||||
public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, final int innerAccessFlags) {
|
||||
@@ -110,27 +110,6 @@ public final class InnerClass implements Cloneable, Node {
|
||||
return innerAccessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of inner class.
|
||||
*/
|
||||
public int getInnerClassIndex() {
|
||||
return innerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name index of inner class.
|
||||
*/
|
||||
public int getInnerNameIndex() {
|
||||
return innerNameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of outer class.
|
||||
*/
|
||||
public int getOuterClassIndex() {
|
||||
return outerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerAccessFlags access flags for this inner class
|
||||
*/
|
||||
@@ -138,6 +117,13 @@ public final class InnerClass implements Cloneable, Node {
|
||||
this.innerAccessFlags = innerAccessFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of inner class.
|
||||
*/
|
||||
public int getInnerClassIndex() {
|
||||
return innerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerClassIndex index into the constant pool for this class
|
||||
*/
|
||||
@@ -145,6 +131,13 @@ public final class InnerClass implements Cloneable, Node {
|
||||
this.innerClassIndex = innerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return name index of inner class.
|
||||
*/
|
||||
public int getInnerNameIndex() {
|
||||
return innerNameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerNameIndex index into the constant pool for this class's name
|
||||
*/
|
||||
@@ -152,6 +145,13 @@ public final class InnerClass implements Cloneable, Node {
|
||||
this.innerNameIndex = innerNameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class index of outer class.
|
||||
*/
|
||||
public int getOuterClassIndex() {
|
||||
return outerClassIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param outerClassIndex index into the constant pool for the owning class
|
||||
*/
|
||||
|
||||
@@ -54,9 +54,9 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O error occurs.
|
||||
*/
|
||||
@@ -70,8 +70,8 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||
* @param length Content length in bytes
|
||||
* @param innerClasses array of inner classes attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
@@ -127,11 +127,6 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
return innerClasses;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<InnerClass> iterator() {
|
||||
return Stream.of(innerClasses).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param innerClasses the array of inner classes
|
||||
*/
|
||||
@@ -139,6 +134,11 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
||||
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<InnerClass> iterator() {
|
||||
return Stream.of(innerClasses).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,7 +28,7 @@ import java.util.Objects;
|
||||
* This class represents the field info structure, i.e., the representation for a variable in the class. See JVM
|
||||
* specification for details.
|
||||
*/
|
||||
public final class JavaField extends FieldOrMethod {
|
||||
public class JavaField extends FieldOrMethod {
|
||||
|
||||
/**
|
||||
* Empty array constant.
|
||||
@@ -36,7 +36,10 @@ public final class JavaField extends FieldOrMethod {
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final JavaField[] EMPTY_ARRAY = {};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final JavaField[] EMPTY_FIELD_ARRAY = {};
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
|
||||
@Override
|
||||
@@ -52,25 +55,14 @@ public final class JavaField extends FieldOrMethod {
|
||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
* 值类型
|
||||
*/
|
||||
static final JavaField[] EMPTY_FIELD_ARRAY = {};
|
||||
|
||||
private int valueType;
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
* 值
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* Construct object from file stream.
|
||||
@@ -92,16 +84,30 @@ public final class JavaField extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accessFlags Access rights of field
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param accessFlags Access rights of field
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public JavaField(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -150,6 +156,22 @@ public final class JavaField extends FieldOrMethod {
|
||||
return Type.getReturnType(getSignature());
|
||||
}
|
||||
|
||||
public int getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public void setValueType(int valueType) {
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
|
||||
* signature.
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.util.Objects;
|
||||
* This class represents the method info structure, i.e., the representation for a method in the class. See JVM
|
||||
* specification for details. A method has access flags, a name, a signature and a number of attributes.
|
||||
*/
|
||||
public final class JavaMethod extends FieldOrMethod {
|
||||
public class JavaMethod extends FieldOrMethod {
|
||||
|
||||
/**
|
||||
* Empty array constant.
|
||||
@@ -35,7 +35,10 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
* @since 6.6.0
|
||||
*/
|
||||
public static final JavaMethod[] EMPTY_ARRAY = {};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final JavaMethod[] EMPTY_METHOD_ARRAY = {};
|
||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||
|
||||
@Override
|
||||
@@ -51,26 +54,6 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Empty array.
|
||||
*/
|
||||
static final JavaMethod[] EMPTY_METHOD_ARRAY = {};
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
// annotations defined on the parameters of a method
|
||||
private ParameterAnnotationEntry[] parameterAnnotationEntries;
|
||||
|
||||
@@ -84,7 +67,7 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
* Construct object from file stream.
|
||||
*
|
||||
* @param file Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
JavaMethod(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException {
|
||||
@@ -92,11 +75,11 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param accessFlags Access rights of method
|
||||
* @param nameIndex Points to field name in constant pool
|
||||
* @param signatureIndex Points to encoded signature
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
* @param attributes Collection of attributes
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public JavaMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
||||
@@ -112,6 +95,20 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
super(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Comparison strategy object
|
||||
*/
|
||||
public static BCELComparator getComparator() {
|
||||
return bcelComparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param comparator Comparison strategy object
|
||||
*/
|
||||
public static void setComparator(final BCELComparator comparator) {
|
||||
bcelComparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@@ -162,7 +159,7 @@ public final class JavaMethod extends FieldOrMethod {
|
||||
|
||||
/**
|
||||
* @return ExceptionTable attribute of method, if any, i.e., list all exceptions the method may throw not exception
|
||||
* handlers!
|
||||
* handlers!
|
||||
*/
|
||||
public ExceptionTable getExceptionTable() {
|
||||
for (final Attribute attribute : super.getAttributes()) {
|
||||
|
||||
@@ -32,10 +32,14 @@ public final class LineNumber implements Cloneable, Node {
|
||||
|
||||
static final LineNumber[] EMPTY_ARRAY = {};
|
||||
|
||||
/** Program Counter (PC) corresponds to line */
|
||||
/**
|
||||
* Program Counter (PC) corresponds to line
|
||||
*/
|
||||
private int startPc;
|
||||
|
||||
/** number in source file */
|
||||
/**
|
||||
* number in source file
|
||||
*/
|
||||
private int lineNumber;
|
||||
|
||||
/**
|
||||
@@ -49,7 +53,7 @@ public final class LineNumber implements Cloneable, Node {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc Program Counter (PC) corresponds to
|
||||
* @param startPc Program Counter (PC) corresponds to
|
||||
* @param lineNumber line number in source file
|
||||
*/
|
||||
public LineNumber(final int startPc, final int lineNumber) {
|
||||
@@ -107,13 +111,6 @@ public final class LineNumber implements Cloneable, Node {
|
||||
return lineNumber & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PC in code
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lineNumber the source line number
|
||||
*/
|
||||
@@ -121,6 +118,13 @@ public final class LineNumber implements Cloneable, Node {
|
||||
this.lineNumber = (short) lineNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PC in code
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc & 0xffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc the pc for this line number
|
||||
*/
|
||||
|
||||
@@ -41,9 +41,9 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param nameIndex Index of name
|
||||
* @param length Content length in bytes
|
||||
* @param input Input stream
|
||||
* @param constantPool Array of constants
|
||||
* @throws IOException if an I/O Exception occurs in readUnsignedShort
|
||||
*/
|
||||
@@ -126,6 +126,13 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
return lineNumberTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lineNumberTable the line number entries for this table
|
||||
*/
|
||||
public void setLineNumberTable(final LineNumber[] lineNumberTable) {
|
||||
this.lineNumberTable = lineNumberTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map byte code positions to source code lines.
|
||||
*
|
||||
@@ -181,13 +188,6 @@ public final class LineNumberTable extends Attribute implements Iterable<LineNum
|
||||
return Stream.of(lineNumberTable).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lineNumberTable the line number entries for this table
|
||||
*/
|
||||
public void setLineNumberTable(final LineNumber[] lineNumberTable) {
|
||||
this.lineNumberTable = lineNumberTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -36,35 +36,28 @@ import java.io.IOException;
|
||||
public final class LocalVariable implements Cloneable, Node {
|
||||
|
||||
static final LocalVariable[] EMPTY_ARRAY = {};
|
||||
|
||||
/**
|
||||
* Range in which the variable is valid.
|
||||
*/
|
||||
private int startPc;
|
||||
|
||||
private int length;
|
||||
|
||||
/**
|
||||
* Index in constant pool of variable name.
|
||||
*/
|
||||
private int nameIndex;
|
||||
|
||||
/**
|
||||
* Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature
|
||||
*/
|
||||
private int signatureIndex;
|
||||
|
||||
/*
|
||||
* Variable is index'th local variable on this method's frame.
|
||||
*/
|
||||
private int index;
|
||||
|
||||
private ConstantPool constantPool;
|
||||
|
||||
/**
|
||||
* Never changes; used to match up with LocalVariableTypeTable entries.
|
||||
*/
|
||||
private final int origIndex;
|
||||
/**
|
||||
* Range in which the variable is valid.
|
||||
*/
|
||||
private int startPc;
|
||||
private int length;
|
||||
/**
|
||||
* Index in constant pool of variable name.
|
||||
*/
|
||||
private int nameIndex;
|
||||
/**
|
||||
* Technically, a decscriptor_index for a local variable table entry and a signatureIndex for a local variable type table entry. Index of variable signature
|
||||
*/
|
||||
private int signatureIndex;
|
||||
/*
|
||||
* Variable is index'th local variable on this method's frame.
|
||||
*/
|
||||
private int index;
|
||||
private ConstantPool constantPool;
|
||||
|
||||
/**
|
||||
* Constructs object from file stream.
|
||||
@@ -164,6 +157,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index of register where variable is stored
|
||||
*/
|
||||
@@ -171,6 +171,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index the index in the local variable table of this variable
|
||||
*/
|
||||
public void setIndex(final int index) { // TODO unused
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Variable is valid within getStartPC() .. getStartPC()+getLength()
|
||||
*/
|
||||
@@ -178,6 +185,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the length of this local variable
|
||||
*/
|
||||
public void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Variable name.
|
||||
*/
|
||||
@@ -192,6 +206,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex the index into the constant pool for the name of this variable
|
||||
*/
|
||||
public void setNameIndex(final int nameIndex) { // TODO unused
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return index of register where variable was originally stored
|
||||
*/
|
||||
@@ -213,41 +234,6 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
return signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Start of range where the variable is valid
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constantPool Constant pool to be used for this object.
|
||||
*/
|
||||
public void setConstantPool(final ConstantPool constantPool) {
|
||||
this.constantPool = constantPool;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index the index in the local variable table of this variable
|
||||
*/
|
||||
public void setIndex(final int index) { // TODO unused
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param length the length of this local variable
|
||||
*/
|
||||
public void setLength(final int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex the index into the constant pool for the name of this variable
|
||||
*/
|
||||
public void setNameIndex(final int nameIndex) { // TODO unused
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param signatureIndex the index into the constant pool for the signature of this variable
|
||||
*/
|
||||
@@ -255,6 +241,13 @@ public final class LocalVariable implements Cloneable, Node {
|
||||
this.signatureIndex = signatureIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Start of range where the variable is valid
|
||||
*/
|
||||
public int getStartPC() {
|
||||
return startPc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startPc Specify range where the local variable is valid.
|
||||
*/
|
||||
|
||||
@@ -40,9 +40,9 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
/**
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param nameIndex Index in constant pool
|
||||
* @param length Content length in bytes
|
||||
* @param input 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.
|
||||
*/
|
||||
@@ -56,10 +56,10 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nameIndex Index in constant pool to 'LocalVariableTable'
|
||||
* @param length Content length in bytes
|
||||
* @param nameIndex Index in constant pool to 'LocalVariableTable'
|
||||
* @param length Content length in bytes
|
||||
* @param localVariableTable Table of local variables
|
||||
* @param constantPool Array of constants
|
||||
* @param constantPool Array of constants
|
||||
*/
|
||||
public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, final ConstantPool constantPool) {
|
||||
super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, constantPool);
|
||||
@@ -116,13 +116,10 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index the variable slot
|
||||
*
|
||||
* @return the first LocalVariable that matches the slot or null if not found
|
||||
*
|
||||
* @deprecated since 5.2 because multiple variables can share the same slot, use getLocalVariable(int index, int pc)
|
||||
* instead.
|
||||
* instead.
|
||||
*/
|
||||
@java.lang.Deprecated
|
||||
public final LocalVariable getLocalVariable(final int index) {
|
||||
@@ -135,10 +132,8 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param index the variable slot
|
||||
* @param pc the current pc that this variable is alive
|
||||
*
|
||||
* @param pc the current pc that this variable is alive
|
||||
* @return the LocalVariable that matches or null if not found
|
||||
*/
|
||||
public final LocalVariable getLocalVariable(final int index, final int pc) {
|
||||
@@ -161,6 +156,10 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
return localVariableTable;
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTable = localVariableTable;
|
||||
}
|
||||
|
||||
public final int getTableLength() {
|
||||
return localVariableTable == null ? 0 : localVariableTable.length;
|
||||
}
|
||||
@@ -170,10 +169,6 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
||||
return Stream.of(localVariableTable).iterator();
|
||||
}
|
||||
|
||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||
this.localVariableTable = localVariableTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return String representation.
|
||||
*/
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 haidnor.jvm.bcel.classfile;
|
||||
|
||||
@@ -27,15 +27,19 @@ import java.io.IOException;
|
||||
* Entry of the parameters table.
|
||||
*
|
||||
* @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>
|
||||
* The MethodParameters Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class MethodParameter implements Cloneable, Node {
|
||||
|
||||
/** Index of the CONSTANT_Utf8_info structure in the constant_pool table representing the name of the parameter */
|
||||
/**
|
||||
* Index of the CONSTANT_Utf8_info structure in the constant_pool table representing the name of the parameter
|
||||
*/
|
||||
private int nameIndex;
|
||||
|
||||
/** The access flags */
|
||||
/**
|
||||
* The access flags
|
||||
*/
|
||||
private int accessFlags;
|
||||
|
||||
public MethodParameter() {
|
||||
@@ -45,7 +49,7 @@ public class MethodParameter implements Cloneable, Node {
|
||||
* Construct object from input stream.
|
||||
*
|
||||
* @param input Input stream
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws IOException if an I/O error occurs.
|
||||
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||
*/
|
||||
MethodParameter(final DataInput input) throws IOException {
|
||||
@@ -85,10 +89,18 @@ public class MethodParameter implements Cloneable, Node {
|
||||
return accessFlags;
|
||||
}
|
||||
|
||||
public void setAccessFlags(final int accessFlags) {
|
||||
this.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
public int getNameIndex() {
|
||||
return nameIndex;
|
||||
}
|
||||
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the parameter.
|
||||
*/
|
||||
@@ -110,12 +122,4 @@ public class MethodParameter implements Cloneable, Node {
|
||||
public boolean isSynthetic() {
|
||||
return (accessFlags & Const.ACC_SYNTHETIC) != 0;
|
||||
}
|
||||
|
||||
public void setAccessFlags(final int accessFlags) {
|
||||
this.accessFlags = accessFlags;
|
||||
}
|
||||
|
||||
public void setNameIndex(final int nameIndex) {
|
||||
this.nameIndex = nameIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.stream.Stream;
|
||||
* This class represents a MethodParameters attribute.
|
||||
*
|
||||
* @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>
|
||||
* The MethodParameters Attribute</a>
|
||||
* @since 6.0
|
||||
*/
|
||||
public class MethodParameters extends Attribute implements Iterable<MethodParameter> {
|
||||
@@ -86,12 +86,12 @@ public class MethodParameters extends Attribute implements Iterable<MethodParame
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(final MethodParameter[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<MethodParameter> iterator() {
|
||||
return Stream.of(parameters).iterator();
|
||||
}
|
||||
|
||||
public void setParameters(final MethodParameter[] parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user