mirror of
https://github.com/FranzHaidnor/haidnorJVM.git
synced 2026-04-03 14:26:16 +00:00
refactor
This commit is contained in:
9
pom.xml
9
pom.xml
@@ -43,6 +43,13 @@
|
|||||||
<version>2.0.7</version>
|
<version>2.0.7</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.26</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
@@ -68,7 +75,7 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<transformers>
|
<transformers>
|
||||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
<mainClass>haidnor.jvm.Main</mainClass>
|
<mainClass>haidnor.jvm.HaidnorJVM</mainClass>
|
||||||
</transformer>
|
</transformer>
|
||||||
</transformers>
|
</transformers>
|
||||||
</configuration>
|
</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 {
|
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
|
* The mother of all exceptions
|
||||||
*/
|
*/
|
||||||
public static final Class<Throwable> THROWABLE = Throwable.class;
|
public static final Class<Throwable> THROWABLE = Throwable.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Super class of any run-time exception
|
* Super class of any run-time exception
|
||||||
*/
|
*/
|
||||||
public static final Class<RuntimeException> RUNTIME_EXCEPTION = RuntimeException.class;
|
public static final Class<RuntimeException> RUNTIME_EXCEPTION = RuntimeException.class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Super class of any linking exception (aka Linkage Error)
|
* 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<NoSuchMethodError> NO_SUCH_METHOD_ERROR = NoSuchMethodError.class;
|
||||||
public static final Class<NoClassDefFoundError> NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.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<UnsatisfiedLinkError> UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class;
|
||||||
|
|
||||||
public static final Class<VerifyError> VERIFY_ERROR = VerifyError.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
|
* Run-Time Exceptions
|
||||||
*/
|
*/
|
||||||
public static final Class<NullPointerException> NULL_POINTER_EXCEPTION = NullPointerException.class;
|
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<ArrayIndexOutOfBoundsException> ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION = ArrayIndexOutOfBoundsException.class;
|
||||||
public static final Class<ArithmeticException> ARITHMETIC_EXCEPTION = ArithmeticException.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<NegativeArraySizeException> NEGATIVE_ARRAY_SIZE_EXCEPTION = NegativeArraySizeException.class;
|
||||||
public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class;
|
public static final Class<ClassCastException> CLASS_CAST_EXCEPTION = ClassCastException.class;
|
||||||
|
|
||||||
public static final Class<IllegalMonitorStateException> ILLEGAL_MONITOR_STATE = IllegalMonitorStateException.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
|
* 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,
|
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
|
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.
|
* Empty array.
|
||||||
*/
|
*/
|
||||||
private static final Class<?>[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
|
private static final Class<?>[] EXCS_INTERFACE_METHOD_RESOLUTION = new Class[0]; // Chapter 5.3 (as below)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty array.
|
* Empty array.
|
||||||
*/
|
*/
|
||||||
private static final Class<?>[] EXCS_STRING_RESOLUTION = new Class[0];
|
private static final Class<?>[] EXCS_STRING_RESOLUTION = new Class[0];
|
||||||
|
|
||||||
// Chapter 5.4 (no errors but the ones that _always_ could happen! How stupid.)
|
// 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};
|
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.
|
* 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
|
* @param extraClasses additional classes, if any
|
||||||
* @return the merged array
|
* @return the merged array
|
||||||
*/
|
*/
|
||||||
public static Class<?>[] createExceptions(final EXCS type, final Class<?>... extraClasses) {
|
public static Class<?>[] createExceptions(final EXCS type, final Class<?>... extraClasses) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
|
case EXCS_CLASS_AND_INTERFACE_RESOLUTION:
|
||||||
return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
|
return mergeExceptions(EXCS_CLASS_AND_INTERFACE_RESOLUTION, extraClasses);
|
||||||
case EXCS_ARRAY_EXCEPTION:
|
case EXCS_ARRAY_EXCEPTION:
|
||||||
return mergeExceptions(EXCS_ARRAY_EXCEPTION, extraClasses);
|
return mergeExceptions(EXCS_ARRAY_EXCEPTION, extraClasses);
|
||||||
case EXCS_FIELD_AND_METHOD_RESOLUTION:
|
case EXCS_FIELD_AND_METHOD_RESOLUTION:
|
||||||
return mergeExceptions(EXCS_FIELD_AND_METHOD_RESOLUTION, extraClasses);
|
return mergeExceptions(EXCS_FIELD_AND_METHOD_RESOLUTION, extraClasses);
|
||||||
case EXCS_INTERFACE_METHOD_RESOLUTION:
|
case EXCS_INTERFACE_METHOD_RESOLUTION:
|
||||||
return mergeExceptions(EXCS_INTERFACE_METHOD_RESOLUTION, extraClasses);
|
return mergeExceptions(EXCS_INTERFACE_METHOD_RESOLUTION, extraClasses);
|
||||||
case EXCS_STRING_RESOLUTION:
|
case EXCS_STRING_RESOLUTION:
|
||||||
return mergeExceptions(EXCS_STRING_RESOLUTION, extraClasses);
|
return mergeExceptions(EXCS_STRING_RESOLUTION, extraClasses);
|
||||||
default:
|
default:
|
||||||
throw new AssertionError("Cannot happen; unexpected enum value: " + type);
|
throw new AssertionError("Cannot happen; unexpected enum value: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,4 +109,12 @@ public final class ExceptionConst {
|
|||||||
return ArrayUtils.addAll(input, extraClasses);
|
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,
|
* @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
|
* @throws ClassNotFoundException if any of the class's superclasses or superinterfaces can't be found
|
||||||
*/
|
*/
|
||||||
public static JavaClass[] getInterfaces(final JavaClass clazz) throws ClassNotFoundException {
|
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,
|
* @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
|
* @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 {
|
public static JavaClass[] getInterfaces(final String className) throws ClassNotFoundException {
|
||||||
return getInterfaces(lookupClass(className));
|
return getInterfaces(lookupClass(className));
|
||||||
@@ -77,6 +77,13 @@ public abstract class Repository {
|
|||||||
return 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
|
* @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
|
* @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.
|
* Tries to find class source using the internal repository instance.
|
||||||
*
|
*
|
||||||
* @see Class
|
|
||||||
* @return JavaClass object for given runtime class
|
* @return JavaClass object for given runtime class
|
||||||
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
* @throws ClassNotFoundException if the class could not be found or parsed correctly
|
||||||
|
* @see Class
|
||||||
*/
|
*/
|
||||||
public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
|
public static JavaClass lookupClass(final Class<?> clazz) throws ClassNotFoundException {
|
||||||
return repository.loadClass(clazz);
|
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
|
* @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) {
|
public static ClassPath.ClassFile lookupClassFile(final String className) {
|
||||||
try (ClassPath path = repository.getClassPath()) {
|
try (ClassPath path = repository.getClassPath()) {
|
||||||
@@ -205,11 +212,4 @@ public abstract class Repository {
|
|||||||
public static void removeClass(final String clazz) {
|
public static void removeClass(final String clazz) {
|
||||||
repository.removeClass(repository.findClass(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;
|
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".
|
* @return Access flags of the object aka. "modifiers".
|
||||||
*/
|
*/
|
||||||
@@ -53,6 +62,15 @@ public abstract class AccessFlags {
|
|||||||
return access_flags;
|
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() {
|
public final boolean isAbstract() {
|
||||||
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
return (access_flags & Const.ACC_ABSTRACT) != 0;
|
||||||
}
|
}
|
||||||
@@ -181,15 +199,6 @@ public abstract class AccessFlags {
|
|||||||
setFlag(Const.ACC_VOLATILE, flag);
|
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) {
|
private void setFlag(final int flag, final boolean set) {
|
||||||
if ((access_flags & flag) != 0) { // Flag is set already
|
if ((access_flags & flag) != 0) { // Flag is set already
|
||||||
if (!set) {
|
if (!set) {
|
||||||
@@ -199,13 +208,4 @@ public abstract class AccessFlags {
|
|||||||
access_flags |= flag;
|
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;
|
private ElementValue defaultValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
AnnotationDefault(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
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 nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param defaultValue the annotation's default value
|
* @param defaultValue the annotation's default value
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,11 +31,21 @@ import java.util.stream.Stream;
|
|||||||
public class AnnotationEntry implements Node {
|
public class AnnotationEntry implements Node {
|
||||||
|
|
||||||
public static final AnnotationEntry[] EMPTY_ARRAY = {};
|
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) {
|
public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) {
|
||||||
// Find attributes that contain annotation data
|
// Find attributes that contain annotation data
|
||||||
return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries()))
|
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<>();
|
annotationEntry.elementValuePairs = new ArrayList<>();
|
||||||
for (int i = 0; i < numElementValuePairs; i++) {
|
for (int i = 0; i < numElementValuePairs; i++) {
|
||||||
annotationEntry.elementValuePairs
|
annotationEntry.elementValuePairs
|
||||||
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
.add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool));
|
||||||
}
|
}
|
||||||
return annotationEntry;
|
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.
|
* 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.
|
* 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> {
|
public abstract class Annotations extends Attribute implements Iterable<AnnotationEntry> {
|
||||||
|
|
||||||
private AnnotationEntry[] annotationTable;
|
|
||||||
private final boolean isRuntimeVisible;
|
private final boolean isRuntimeVisible;
|
||||||
|
private AnnotationEntry[] annotationTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an instance.
|
* Constructs an instance.
|
||||||
@@ -45,7 +45,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
|||||||
* @param isRuntimeVisible whether this Annotation visible at runtime
|
* @param isRuntimeVisible whether this Annotation visible at runtime
|
||||||
*/
|
*/
|
||||||
public Annotations(final byte annotationType, final int nameIndex, final int length, final AnnotationEntry[] annotationTable,
|
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);
|
super(annotationType, nameIndex, length, constantPool);
|
||||||
this.annotationTable = annotationTable;
|
this.annotationTable = annotationTable;
|
||||||
this.isRuntimeVisible = isRuntimeVisible;
|
this.isRuntimeVisible = isRuntimeVisible;
|
||||||
@@ -63,7 +63,7 @@ public abstract class Annotations extends Attribute implements Iterable<Annotati
|
|||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
Annotations(final byte annotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool,
|
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);
|
this(annotationType, nameIndex, length, (AnnotationEntry[]) null, constantPool, isRuntimeVisible);
|
||||||
final int annotationTableLength = input.readUnsignedShort();
|
final int annotationTableLength = input.readUnsignedShort();
|
||||||
annotationTable = new AnnotationEntry[annotationTableLength];
|
annotationTable = new AnnotationEntry[annotationTableLength];
|
||||||
|
|||||||
@@ -53,22 +53,63 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public abstract class Attribute implements Cloneable, Node {
|
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.
|
* Empty array.
|
||||||
*
|
*
|
||||||
* @since 6.6.0
|
* @since 6.6.0
|
||||||
*/
|
*/
|
||||||
public static final Attribute[] EMPTY_ARRAY = {};
|
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
|
* 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.
|
* 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
|
* @param unknownAttributeReader the reader object
|
||||||
*/
|
*/
|
||||||
public static void addAttributeReader(final String name, final UnknownAttributeReader unknownAttributeReader) {
|
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
|
* 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.
|
* is called by the Field and Method constructor methods.
|
||||||
*
|
*
|
||||||
* @see JavaField
|
* @param dataInput Input stream
|
||||||
* @see JavaMethod
|
|
||||||
*
|
|
||||||
* @param dataInput Input stream
|
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @return Attribute
|
* @return Attribute
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
|
* @see JavaField
|
||||||
|
* @see JavaMethod
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public static Attribute readAttribute(final DataInput dataInput, final ConstantPool constantPool) throws IOException {
|
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'
|
// Call proper constructor, depending on 'tag'
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Const.ATTR_UNKNOWN:
|
case Const.ATTR_UNKNOWN:
|
||||||
final Object r = READERS.get(name);
|
final Object r = READERS.get(name);
|
||||||
if (r instanceof UnknownAttributeReader) {
|
if (r instanceof UnknownAttributeReader) {
|
||||||
return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool);
|
return ((UnknownAttributeReader) r).createAttribute(nameIndex, length, dataInput, constantPool);
|
||||||
}
|
}
|
||||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_CONSTANT_VALUE:
|
case Const.ATTR_CONSTANT_VALUE:
|
||||||
return new ConstantValue(nameIndex, length, dataInput, constantPool);
|
return new ConstantValue(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_SOURCE_FILE:
|
case Const.ATTR_SOURCE_FILE:
|
||||||
return new SourceFile(nameIndex, length, dataInput, constantPool);
|
return new SourceFile(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_CODE:
|
case Const.ATTR_CODE:
|
||||||
return new Code(nameIndex, length, dataInput, constantPool);
|
return new Code(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_EXCEPTIONS:
|
case Const.ATTR_EXCEPTIONS:
|
||||||
return new ExceptionTable(nameIndex, length, dataInput, constantPool);
|
return new ExceptionTable(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_LINE_NUMBER_TABLE:
|
case Const.ATTR_LINE_NUMBER_TABLE:
|
||||||
return new LineNumberTable(nameIndex, length, dataInput, constantPool);
|
return new LineNumberTable(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
case Const.ATTR_LOCAL_VARIABLE_TABLE:
|
||||||
return new LocalVariableTable(nameIndex, length, dataInput, constantPool);
|
return new LocalVariableTable(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_INNER_CLASSES:
|
case Const.ATTR_INNER_CLASSES:
|
||||||
return new InnerClasses(nameIndex, length, dataInput, constantPool);
|
return new InnerClasses(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_SYNTHETIC:
|
case Const.ATTR_SYNTHETIC:
|
||||||
return new Synthetic(nameIndex, length, dataInput, constantPool);
|
return new Synthetic(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_DEPRECATED:
|
case Const.ATTR_DEPRECATED:
|
||||||
return new Deprecated(nameIndex, length, dataInput, constantPool);
|
return new Deprecated(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_PMG:
|
case Const.ATTR_PMG:
|
||||||
return new PMGClass(nameIndex, length, dataInput, constantPool);
|
return new PMGClass(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_SIGNATURE:
|
case Const.ATTR_SIGNATURE:
|
||||||
return new Signature(nameIndex, length, dataInput, constantPool);
|
return new Signature(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_STACK_MAP:
|
case Const.ATTR_STACK_MAP:
|
||||||
// old style stack map: unneeded for JDK5 and below;
|
// old style stack map: unneeded for JDK5 and below;
|
||||||
// illegal(?) for JDK6 and above. So just delete with a warning.
|
// illegal(?) for JDK6 and above. So just delete with a warning.
|
||||||
println("Warning: Obsolete StackMap attribute ignored.");
|
println("Warning: Obsolete StackMap attribute ignored.");
|
||||||
return new Unknown(nameIndex, length, dataInput, constantPool);
|
return new Unknown(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
case Const.ATTR_RUNTIME_VISIBLE_ANNOTATIONS:
|
||||||
return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
return new RuntimeVisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
case Const.ATTR_RUNTIME_INVISIBLE_ANNOTATIONS:
|
||||||
return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
return new RuntimeInvisibleAnnotations(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
case Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS:
|
||||||
return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
return new RuntimeVisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
case Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS:
|
||||||
return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
return new RuntimeInvisibleParameterAnnotations(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_ANNOTATION_DEFAULT:
|
case Const.ATTR_ANNOTATION_DEFAULT:
|
||||||
return new AnnotationDefault(nameIndex, length, dataInput, constantPool);
|
return new AnnotationDefault(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
case Const.ATTR_LOCAL_VARIABLE_TYPE_TABLE:
|
||||||
return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool);
|
return new LocalVariableTypeTable(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_ENCLOSING_METHOD:
|
case Const.ATTR_ENCLOSING_METHOD:
|
||||||
return new EnclosingMethod(nameIndex, length, dataInput, constantPool);
|
return new EnclosingMethod(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_STACK_MAP_TABLE:
|
case Const.ATTR_STACK_MAP_TABLE:
|
||||||
// read new style stack map: StackMapTable. The rest of the code
|
// read new style stack map: StackMapTable. The rest of the code
|
||||||
// calls this a StackMap for historical reasons.
|
// calls this a StackMap for historical reasons.
|
||||||
return new StackMap(nameIndex, length, dataInput, constantPool);
|
return new StackMap(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_BOOTSTRAP_METHODS:
|
case Const.ATTR_BOOTSTRAP_METHODS:
|
||||||
return new BootstrapMethods(nameIndex, length, dataInput, constantPool);
|
return new BootstrapMethods(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_METHOD_PARAMETERS:
|
case Const.ATTR_METHOD_PARAMETERS:
|
||||||
return new MethodParameters(nameIndex, length, dataInput, constantPool);
|
return new MethodParameters(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_MODULE:
|
case Const.ATTR_MODULE:
|
||||||
return new Module(nameIndex, length, dataInput, constantPool);
|
return new Module(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_MODULE_PACKAGES:
|
case Const.ATTR_MODULE_PACKAGES:
|
||||||
return new ModulePackages(nameIndex, length, dataInput, constantPool);
|
return new ModulePackages(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_MODULE_MAIN_CLASS:
|
case Const.ATTR_MODULE_MAIN_CLASS:
|
||||||
return new ModuleMainClass(nameIndex, length, dataInput, constantPool);
|
return new ModuleMainClass(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_NEST_HOST:
|
case Const.ATTR_NEST_HOST:
|
||||||
return new NestHost(nameIndex, length, dataInput, constantPool);
|
return new NestHost(nameIndex, length, dataInput, constantPool);
|
||||||
case Const.ATTR_NEST_MEMBERS:
|
case Const.ATTR_NEST_MEMBERS:
|
||||||
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
return new NestMembers(nameIndex, length, dataInput, constantPool);
|
||||||
default:
|
default:
|
||||||
// Never reached
|
// Never reached
|
||||||
throw new IllegalStateException("Unrecognized attribute type tag parsed: " + tag);
|
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
|
* 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.
|
* is called by the Field and Method constructor methods.
|
||||||
*
|
*
|
||||||
* @see JavaField
|
|
||||||
* @see JavaMethod
|
|
||||||
*
|
|
||||||
* @param dataInputStream Input stream
|
* @param dataInputStream Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @return Attribute
|
* @return Attribute
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
|
* @see JavaField
|
||||||
|
* @see JavaMethod
|
||||||
*/
|
*/
|
||||||
public static Attribute readAttribute(final DataInputStream dataInputStream, final ConstantPool constantPool) throws IOException {
|
public static Attribute readAttribute(final DataInputStream dataInputStream, final ConstantPool constantPool) throws IOException {
|
||||||
return readAttribute((DataInput) dataInputStream, constantPool);
|
return readAttribute((DataInput) dataInputStream, constantPool);
|
||||||
@@ -209,53 +248,6 @@ public abstract class Attribute implements Cloneable, Node {
|
|||||||
READERS.remove(name);
|
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.
|
* 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.
|
* 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;
|
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.
|
* @return Length of attribute field in bytes.
|
||||||
*/
|
*/
|
||||||
@@ -313,6 +313,13 @@ public abstract class Attribute implements Cloneable, Node {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param length length in bytes.
|
||||||
|
*/
|
||||||
|
public final void setLength(final int length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Name of attribute
|
* @return Name of attribute
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
@@ -328,28 +335,6 @@ public abstract class Attribute implements Cloneable, Node {
|
|||||||
return name_index;
|
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.
|
* @param nameIndex of attribute.
|
||||||
*/
|
*/
|
||||||
@@ -357,6 +342,13 @@ public abstract class Attribute implements Cloneable, Node {
|
|||||||
this.name_index = nameIndex;
|
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.
|
* @return attribute name.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,15 +29,19 @@ import java.util.Arrays;
|
|||||||
* and an array of the bootstrap arguments.
|
* 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 :
|
* @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
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public class BootstrapMethod implements Cloneable {
|
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;
|
private int bootstrapMethodRef;
|
||||||
|
|
||||||
/** Array of references to the constant_pool table */
|
/**
|
||||||
|
* Array of references to the constant_pool table
|
||||||
|
*/
|
||||||
private int[] bootstrapArguments;
|
private int[] bootstrapArguments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,20 +114,6 @@ public class BootstrapMethod implements Cloneable {
|
|||||||
return bootstrapArguments;
|
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
|
* @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info
|
||||||
*/
|
*/
|
||||||
@@ -131,6 +121,13 @@ public class BootstrapMethod implements Cloneable {
|
|||||||
this.bootstrapArguments = bootstrapArguments;
|
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
|
* @param bootstrapMethodRef int index into constant_pool of CONSTANT_MethodHandle
|
||||||
*/
|
*/
|
||||||
@@ -138,6 +135,13 @@ public class BootstrapMethod implements Cloneable {
|
|||||||
this.bootstrapMethodRef = bootstrapMethodRef;
|
this.bootstrapMethodRef = bootstrapMethodRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return count of number of boostrap arguments
|
||||||
|
*/
|
||||||
|
public int getNumBootstrapArguments() {
|
||||||
|
return bootstrapArguments.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import java.util.stream.Stream;
|
|||||||
* This class represents a BootstrapMethods attribute.
|
* 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 :
|
* @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
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public class BootstrapMethods extends Attribute implements Iterable<BootstrapMethod> {
|
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 nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param bootstrapMethods array of bootstrap methods
|
* @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) {
|
public BootstrapMethods(final int nameIndex, final int length, final BootstrapMethod[] bootstrapMethods, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_BOOTSTRAP_METHODS, nameIndex, length, 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.
|
* Construct object from Input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -122,11 +122,6 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
|||||||
return bootstrapMethods;
|
return bootstrapMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<BootstrapMethod> iterator() {
|
|
||||||
return Stream.of(bootstrapMethods).iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bootstrapMethods the array of bootstrap methods
|
* @param bootstrapMethods the array of bootstrap methods
|
||||||
*/
|
*/
|
||||||
@@ -134,6 +129,11 @@ public class BootstrapMethods extends Attribute implements Iterable<BootstrapMet
|
|||||||
this.bootstrapMethods = bootstrapMethods;
|
this.bootstrapMethods = bootstrapMethods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<BootstrapMethod> iterator() {
|
||||||
|
return Stream.of(bootstrapMethods).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @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
|
* 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
|
* <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.
|
* appropriate exception is propagated back to the caller.
|
||||||
*
|
* <p>
|
||||||
* The structure and the names comply, except for a few conveniences, exactly with the
|
* The structure and the names comply, except for a few conveniences, exactly with the
|
||||||
* <a href="http://docs.oracle.com/javase/specs/"> JVM specification 1.0</a>. See this paper for further details about
|
* <a href="http://docs.oracle.com/javase/specs/"> JVM specification 1.0</a>. See this paper for further details about
|
||||||
* the structure of a bytecode file.
|
* the structure of a bytecode file.
|
||||||
@@ -34,9 +34,10 @@ import java.util.zip.ZipFile;
|
|||||||
public final class ClassParser {
|
public final class ClassParser {
|
||||||
|
|
||||||
private static final int BUFSIZE = 8192;
|
private static final int BUFSIZE = 8192;
|
||||||
private DataInputStream dataInputStream;
|
|
||||||
private final boolean fileOwned;
|
private final boolean fileOwned;
|
||||||
private final String fileName;
|
private final String fileName;
|
||||||
|
private final boolean isZip; // Loaded from zip file
|
||||||
|
private DataInputStream dataInputStream;
|
||||||
private String zipFile;
|
private String zipFile;
|
||||||
private int classNameIndex;
|
private int classNameIndex;
|
||||||
private int superclassNameIndex;
|
private int superclassNameIndex;
|
||||||
@@ -48,13 +49,12 @@ public final class ClassParser {
|
|||||||
private JavaField[] fields; // class fields, i.e., its variables
|
private JavaField[] fields; // class fields, i.e., its variables
|
||||||
private JavaMethod[] methods; // methods defined in the class
|
private JavaMethod[] methods; // methods defined in the class
|
||||||
private Attribute[] attributes; // attributes 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.
|
* Parses class from the given stream.
|
||||||
*
|
*
|
||||||
* @param inputStream Input stream
|
* @param inputStream Input stream
|
||||||
* @param fileName File name
|
* @param fileName File name
|
||||||
*/
|
*/
|
||||||
public ClassParser(final InputStream inputStream, final String fileName) {
|
public ClassParser(final InputStream inputStream, final String fileName) {
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
@@ -82,7 +82,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Parses class from given .class file in a ZIP-archive
|
* Parses class from given .class file in a ZIP-archive
|
||||||
*
|
*
|
||||||
* @param zipFile zip file name
|
* @param zipFile zip file name
|
||||||
* @param fileName file name
|
* @param fileName file name
|
||||||
*/
|
*/
|
||||||
public ClassParser(final String zipFile, final String fileName) {
|
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).
|
* not include verification of the byte code as it is performed by the java interpreter).
|
||||||
*
|
*
|
||||||
* @return Class object representing the parsed class file
|
* @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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
public JavaClass parse() throws IOException, ClassFormatException {
|
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 the information we have gathered in a new object
|
||||||
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, accessFlags, constantPool, interfaces, fields, methods, attributes,
|
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.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readAttributes() throws IOException, ClassFormatException {
|
private void readAttributes() throws IOException, ClassFormatException {
|
||||||
@@ -192,7 +192,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Reads information about the class and its super class.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readClassInfo() throws IOException, ClassFormatException {
|
private void readClassInfo() throws IOException, ClassFormatException {
|
||||||
@@ -213,7 +213,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Reads constant pool entries.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readConstantPool() throws IOException, ClassFormatException {
|
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.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readFields() throws IOException, ClassFormatException {
|
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.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readID() throws IOException, ClassFormatException {
|
private void readID() throws IOException, ClassFormatException {
|
||||||
@@ -250,7 +250,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Reads information about the interfaces implemented by this class.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readInterfaces() throws IOException, ClassFormatException {
|
private void readInterfaces() throws IOException, ClassFormatException {
|
||||||
@@ -264,7 +264,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Reads information about the methods of the class.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readMethods() throws IOException {
|
private void readMethods() throws IOException {
|
||||||
@@ -278,7 +278,7 @@ public final class ClassParser {
|
|||||||
/**
|
/**
|
||||||
* Reads major and minor version of compiler which created the file.
|
* 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
private void readVersion() throws IOException, ClassFormatException {
|
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
|
* 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
|
* <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.
|
* 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
|
* 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.
|
* <em>LocalVariableTable</em> which contains information about the local variables.
|
||||||
*
|
*
|
||||||
@@ -52,6 +52,7 @@ import java.util.Arrays;
|
|||||||
* attribute_info attributes[attributes_count];
|
* attribute_info attributes[attributes_count];
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @see Attribute
|
* @see Attribute
|
||||||
* @see CodeException
|
* @see CodeException
|
||||||
* @see LineNumberTable
|
* @see LineNumberTable
|
||||||
@@ -77,9 +78,9 @@ public final class Code extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param file Input stream
|
* @param file Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
Code(final int nameIndex, final int length, final DataInput file, final ConstantPool constantPool) throws IOException {
|
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 nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param maxStack Maximum size of stack
|
* @param maxStack Maximum size of stack
|
||||||
* @param maxLocals Number of local variables
|
* @param maxLocals Number of local variables
|
||||||
* @param code Actual byte code
|
* @param code Actual byte code
|
||||||
* @param exceptionTable of handled exceptions
|
* @param exceptionTable of handled exceptions
|
||||||
* @param attributes Attributes of code: LineNumber or LocalVariable
|
* @param attributes Attributes of code: LineNumber or LocalVariable
|
||||||
* @param constantPool Array of constants
|
* @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,
|
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);
|
super(Const.ATTR_CODE, nameIndex, length, constantPool);
|
||||||
this.maxStack = Args.requireU2(maxStack, "maxStack");
|
this.maxStack = Args.requireU2(maxStack, "maxStack");
|
||||||
this.maxLocals = Args.requireU2(maxLocals, "maxLocals");
|
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
|
* @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() {
|
private int calculateLength() {
|
||||||
int len = 0;
|
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
|
* @param constantPool the constant pool to duplicate
|
||||||
|
* @return deep copy of this attribute
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Attribute copy(final ConstantPool constantPool) {
|
public Attribute copy(final ConstantPool constantPool) {
|
||||||
@@ -209,6 +209,14 @@ public final class Code extends Attribute {
|
|||||||
return attributes;
|
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.
|
* @return Actual byte code of the method.
|
||||||
*/
|
*/
|
||||||
@@ -216,6 +224,14 @@ public final class Code extends Attribute {
|
|||||||
return code;
|
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.
|
* @return Table of handled exceptions.
|
||||||
* @see CodeException
|
* @see CodeException
|
||||||
@@ -224,15 +240,23 @@ public final class Code extends Attribute {
|
|||||||
return exceptionTable;
|
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
|
* @return the internal length of this code attribute (minus the first 6 bytes) and excluding all its attributes
|
||||||
*/
|
*/
|
||||||
private int getInternalLength() {
|
private int getInternalLength() {
|
||||||
return 2 /* maxStack */ + 2 /* maxLocals */ + 4 /* code length */
|
return 2 /* maxStack */ + 2 /* maxLocals */ + 4 /* code length */
|
||||||
+ code.length /* byte-code */
|
+ code.length /* byte-code */
|
||||||
+ 2 /* exception-table length */
|
+ 2 /* exception-table length */
|
||||||
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
|
||||||
+ 2 /* attributes count */;
|
+ 2 /* attributes count */;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -266,37 +290,6 @@ public final class Code extends Attribute {
|
|||||||
return maxLocals;
|
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
|
* @param maxLocals maximum number of local variables
|
||||||
*/
|
*/
|
||||||
@@ -304,6 +297,13 @@ public final class Code extends Attribute {
|
|||||||
this.maxLocals = maxLocals;
|
this.maxLocals = maxLocals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Maximum size of stack used by this method.
|
||||||
|
*/
|
||||||
|
public int getMaxStack() {
|
||||||
|
return maxStack;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param maxStack maximum stack size
|
* @param maxStack maximum stack size
|
||||||
*/
|
*/
|
||||||
@@ -328,7 +328,7 @@ public final class Code extends Attribute {
|
|||||||
public String toString(final boolean verbose) {
|
public String toString(final boolean verbose) {
|
||||||
final StringBuilder buf = new StringBuilder(100); // CHECKSTYLE IGNORE MagicNumber
|
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")
|
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) {
|
if (exceptionTable.length > 0) {
|
||||||
buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
|
buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n");
|
||||||
for (final CodeException exception : exceptionTable) {
|
for (final CodeException exception : exceptionTable) {
|
||||||
|
|||||||
@@ -154,27 +154,6 @@ public final class CodeException implements Cloneable, Node {
|
|||||||
return catchType;
|
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
|
* @param catchType the type of exception that is caught
|
||||||
*/
|
*/
|
||||||
@@ -182,6 +161,13 @@ public final class CodeException implements Cloneable, Node {
|
|||||||
this.catchType = catchType;
|
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
|
* @param endPc end of handled block
|
||||||
*/
|
*/
|
||||||
@@ -189,6 +175,13 @@ public final class CodeException implements Cloneable, Node {
|
|||||||
this.endPc = endPc;
|
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
|
* @param handlerPc where the actual code is
|
||||||
*/
|
*/
|
||||||
@@ -196,6 +189,13 @@ public final class CodeException implements Cloneable, Node {
|
|||||||
this.handlerPc = handlerPc;
|
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
|
* @param startPc start of handled block
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -45,6 +45,15 @@ public abstract class Constant implements Cloneable, Node {
|
|||||||
return THIS.toString().hashCode();
|
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
|
* @return Comparison strategy object
|
||||||
@@ -53,64 +62,6 @@ public abstract class Constant implements Cloneable, Node {
|
|||||||
return bcelComparator;
|
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
|
* 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.
|
* '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
|
* 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.
|
* 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.
|
* Initialize instance from file data.
|
||||||
*
|
*
|
||||||
* @param tag Constant type tag
|
* @param tag Constant type tag
|
||||||
* @param file Input stream
|
* @param file Input stream
|
||||||
* @throws IOException if an I/O error occurs.
|
* @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
|
* @param nameAndTypeIndex and the field signature
|
||||||
*/
|
*/
|
||||||
protected ConstantCP(final byte tag, final int classIndex, final int nameAndTypeIndex) {
|
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 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
|
* @param classIndex points to Constant_class
|
||||||
*/
|
*/
|
||||||
@@ -121,6 +114,13 @@ public abstract class ConstantCP extends Constant {
|
|||||||
this.class_index = classIndex;
|
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
|
* @param nameAndTypeIndex points to Constant_NameAndType
|
||||||
*/
|
*/
|
||||||
@@ -130,8 +130,8 @@ public abstract class ConstantCP extends Constant {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*
|
* <p>
|
||||||
* not final as ConstantInvokeDynamic needs to modify
|
* not final as ConstantInvokeDynamic needs to modify
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@@ -88,6 +88,13 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes the raw bytes that represent the double value
|
||||||
|
*/
|
||||||
|
public void setBytes(final double bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Double object
|
* @return Double object
|
||||||
*/
|
*/
|
||||||
@@ -96,13 +103,6 @@ public final class ConstantDouble extends Constant implements ConstantObject {
|
|||||||
return Double.valueOf(bytes);
|
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.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @see Constant
|
* @see Constant
|
||||||
* @see <a href="https://bugs.openjdk.java.net/secure/attachment/74618/constant-dynamic.html"> Change request for JEP
|
* @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
|
* @since 6.3
|
||||||
*/
|
*/
|
||||||
public final class ConstantDynamic extends ConstantCP {
|
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.
|
* @return Reference (index) to bootstrap method this constant refers to.
|
||||||
*
|
* <p>
|
||||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public int getBootstrapMethodAttrIndex() {
|
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
|
* @param nameAndTypeIndex and the Field signature
|
||||||
*/
|
*/
|
||||||
public ConstantFieldref(final int classIndex, final int nameAndTypeIndex) {
|
public ConstantFieldref(final int classIndex, final int nameAndTypeIndex) {
|
||||||
|
|||||||
@@ -89,6 +89,13 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes the raw bytes that represent this float
|
||||||
|
*/
|
||||||
|
public void setBytes(final float bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Float object
|
* @return Float object
|
||||||
*/
|
*/
|
||||||
@@ -97,13 +104,6 @@ public final class ConstantFloat extends Constant implements ConstantObject {
|
|||||||
return Float.valueOf(bytes);
|
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.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -88,6 +88,13 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes the raw bytes that represent this integer
|
||||||
|
*/
|
||||||
|
public void setBytes(final int bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Integer object
|
* @return Integer object
|
||||||
*/
|
*/
|
||||||
@@ -96,13 +103,6 @@ public final class ConstantInteger extends Constant implements ConstantObject {
|
|||||||
return Integer.valueOf(bytes);
|
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.
|
* @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
|
* @param nameAndTypeIndex and the method signature
|
||||||
*/
|
*/
|
||||||
public ConstantInterfaceMethodref(final int classIndex, final int nameAndTypeIndex) {
|
public ConstantInterfaceMethodref(final int classIndex, final int nameAndTypeIndex) {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import java.io.IOException;
|
|||||||
*
|
*
|
||||||
* @see Constant
|
* @see Constant
|
||||||
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4.10"> The
|
* @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
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public final class ConstantInvokeDynamic extends ConstantCP {
|
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.
|
* @return Reference (index) to bootstrap method this constant refers to.
|
||||||
*
|
* <p>
|
||||||
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
* Note that this method is a functional duplicate of getClassIndex for use by ConstantInvokeDynamic.
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public int getBootstrapMethodAttrIndex() {
|
public int getBootstrapMethodAttrIndex() {
|
||||||
|
|||||||
@@ -88,6 +88,13 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes the raw bytes that represent this long
|
||||||
|
*/
|
||||||
|
public void setBytes(final long bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Long object
|
* @return Long object
|
||||||
*/
|
*/
|
||||||
@@ -96,13 +103,6 @@ public final class ConstantLong extends Constant implements ConstantObject {
|
|||||||
return Long.valueOf(bytes);
|
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.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -86,14 +86,14 @@ public final class ConstantMethodHandle extends Constant {
|
|||||||
return referenceIndex;
|
return referenceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getReferenceKind() {
|
|
||||||
return referenceKind;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReferenceIndex(final int referenceIndex) {
|
public void setReferenceIndex(final int referenceIndex) {
|
||||||
this.referenceIndex = referenceIndex;
|
this.referenceIndex = referenceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getReferenceKind() {
|
||||||
|
return referenceKind;
|
||||||
|
}
|
||||||
|
|
||||||
public void setReferenceKind(final int referenceKind) {
|
public void setReferenceKind(final int referenceKind) {
|
||||||
this.referenceKind = 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
|
* @param nameAndTypeIndex and the method signature
|
||||||
*/
|
*/
|
||||||
public ConstantMethodref(final int classIndex, final int nameAndTypeIndex) {
|
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
|
* @param signatureIndex and its signature
|
||||||
*/
|
*/
|
||||||
public ConstantNameAndType(final int nameIndex, final int signatureIndex) {
|
public ConstantNameAndType(final int nameIndex, final int signatureIndex) {
|
||||||
@@ -100,6 +100,13 @@ public final class ConstantNameAndType extends Constant {
|
|||||||
return nameIndex;
|
return nameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param nameIndex the name index of this constant
|
||||||
|
*/
|
||||||
|
public void setNameIndex(final int nameIndex) {
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return signature
|
* @return signature
|
||||||
*/
|
*/
|
||||||
@@ -114,13 +121,6 @@ public final class ConstantNameAndType extends Constant {
|
|||||||
return signatureIndex;
|
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
|
* @param signatureIndex the signature index in the constant pool of this type
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,34 +35,6 @@ import java.util.Iterator;
|
|||||||
*/
|
*/
|
||||||
public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
||||||
|
|
||||||
private static String escape(final String str) {
|
|
||||||
final int len = str.length();
|
|
||||||
final StringBuilder buf = new StringBuilder(len + 5);
|
|
||||||
final char[] ch = str.toCharArray();
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
switch (ch[i]) {
|
|
||||||
case '\n':
|
|
||||||
buf.append("\\n");
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
buf.append("\\r");
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
buf.append("\\t");
|
|
||||||
break;
|
|
||||||
case '\b':
|
|
||||||
buf.append("\\b");
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
buf.append("\\\"");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
buf.append(ch[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Constant[] constantPool;
|
private Constant[] constantPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,6 +72,34 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String escape(final String str) {
|
||||||
|
final int len = str.length();
|
||||||
|
final StringBuilder buf = new StringBuilder(len + 5);
|
||||||
|
final char[] ch = str.toCharArray();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
switch (ch[i]) {
|
||||||
|
case '\n':
|
||||||
|
buf.append("\\n");
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
buf.append("\\r");
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
buf.append("\\t");
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
buf.append("\\b");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
buf.append("\\\"");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
buf.append(ch[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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,
|
* 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.
|
* attributes, etc. spawns a tree of objects.
|
||||||
@@ -123,72 +123,72 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
int i;
|
int i;
|
||||||
final byte tag = c.getTag();
|
final byte tag = c.getTag();
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Const.CONSTANT_Class:
|
case Const.CONSTANT_Class:
|
||||||
i = ((ConstantClass) c).getNameIndex();
|
i = ((ConstantClass) c).getNameIndex();
|
||||||
c = getConstantUtf8(i);
|
c = getConstantUtf8(i);
|
||||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_String:
|
case Const.CONSTANT_String:
|
||||||
i = ((ConstantString) c).getStringIndex();
|
i = ((ConstantString) c).getStringIndex();
|
||||||
c = getConstantUtf8(i);
|
c = getConstantUtf8(i);
|
||||||
str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
|
str = "\"" + escape(((ConstantUtf8) c).getBytes()) + "\"";
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Utf8:
|
case Const.CONSTANT_Utf8:
|
||||||
str = ((ConstantUtf8) c).getBytes();
|
str = ((ConstantUtf8) c).getBytes();
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Double:
|
case Const.CONSTANT_Double:
|
||||||
str = String.valueOf(((ConstantDouble) c).getBytes());
|
str = String.valueOf(((ConstantDouble) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Float:
|
case Const.CONSTANT_Float:
|
||||||
str = String.valueOf(((ConstantFloat) c).getBytes());
|
str = String.valueOf(((ConstantFloat) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Long:
|
case Const.CONSTANT_Long:
|
||||||
str = String.valueOf(((ConstantLong) c).getBytes());
|
str = String.valueOf(((ConstantLong) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Integer:
|
case Const.CONSTANT_Integer:
|
||||||
str = String.valueOf(((ConstantInteger) c).getBytes());
|
str = String.valueOf(((ConstantInteger) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_NameAndType:
|
case Const.CONSTANT_NameAndType:
|
||||||
str = constantToString(((ConstantNameAndType) c).getNameIndex(), Const.CONSTANT_Utf8) + " "
|
str = constantToString(((ConstantNameAndType) c).getNameIndex(), Const.CONSTANT_Utf8) + " "
|
||||||
+ constantToString(((ConstantNameAndType) c).getSignatureIndex(), Const.CONSTANT_Utf8);
|
+ constantToString(((ConstantNameAndType) c).getSignatureIndex(), Const.CONSTANT_Utf8);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_InterfaceMethodref:
|
case Const.CONSTANT_InterfaceMethodref:
|
||||||
case Const.CONSTANT_Methodref:
|
case Const.CONSTANT_Methodref:
|
||||||
case Const.CONSTANT_Fieldref:
|
case Const.CONSTANT_Fieldref:
|
||||||
str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) + "."
|
str = constantToString(((ConstantCP) c).getClassIndex(), Const.CONSTANT_Class) + "."
|
||||||
+ constantToString(((ConstantCP) c).getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
+ constantToString(((ConstantCP) c).getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_MethodHandle:
|
case Const.CONSTANT_MethodHandle:
|
||||||
// Note that the ReferenceIndex may point to a Fieldref, Methodref or
|
// Note that the ReferenceIndex may point to a Fieldref, Methodref or
|
||||||
// InterfaceMethodref - so we need to peek ahead to get the actual type.
|
// InterfaceMethodref - so we need to peek ahead to get the actual type.
|
||||||
final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
|
final ConstantMethodHandle cmh = (ConstantMethodHandle) c;
|
||||||
str = Const.getMethodHandleName(cmh.getReferenceKind()) + " "
|
str = Const.getMethodHandleName(cmh.getReferenceKind()) + " "
|
||||||
+ constantToString(cmh.getReferenceIndex(), getConstant(cmh.getReferenceIndex()).getTag());
|
+ constantToString(cmh.getReferenceIndex(), getConstant(cmh.getReferenceIndex()).getTag());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_MethodType:
|
case Const.CONSTANT_MethodType:
|
||||||
final ConstantMethodType cmt = (ConstantMethodType) c;
|
final ConstantMethodType cmt = (ConstantMethodType) c;
|
||||||
str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
|
str = constantToString(cmt.getDescriptorIndex(), Const.CONSTANT_Utf8);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_InvokeDynamic:
|
case Const.CONSTANT_InvokeDynamic:
|
||||||
final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
|
final ConstantInvokeDynamic cid = (ConstantInvokeDynamic) c;
|
||||||
str = cid.getBootstrapMethodAttrIndex() + ":" + constantToString(cid.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
str = cid.getBootstrapMethodAttrIndex() + ":" + constantToString(cid.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Dynamic:
|
case Const.CONSTANT_Dynamic:
|
||||||
final ConstantDynamic cd = (ConstantDynamic) c;
|
final ConstantDynamic cd = (ConstantDynamic) c;
|
||||||
str = cd.getBootstrapMethodAttrIndex() + ":" + constantToString(cd.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
str = cd.getBootstrapMethodAttrIndex() + ":" + constantToString(cd.getNameAndTypeIndex(), Const.CONSTANT_NameAndType);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Module:
|
case Const.CONSTANT_Module:
|
||||||
i = ((ConstantModule) c).getNameIndex();
|
i = ((ConstantModule) c).getNameIndex();
|
||||||
c = getConstantUtf8(i);
|
c = getConstantUtf8(i);
|
||||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Package:
|
case Const.CONSTANT_Package:
|
||||||
i = ((ConstantPackage) c).getNameIndex();
|
i = ((ConstantPackage) c).getNameIndex();
|
||||||
c = getConstantUtf8(i);
|
c = getConstantUtf8(i);
|
||||||
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
str = Utility.compactClassName(((ConstantUtf8) c).getBytes(), false);
|
||||||
break;
|
break;
|
||||||
default: // Never reached
|
default: // Never reached
|
||||||
throw new IllegalArgumentException("Unknown constant type " + tag);
|
throw new IllegalArgumentException("Unknown constant type " + tag);
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -249,8 +249,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
*
|
*
|
||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @return Constant value
|
* @return Constant value
|
||||||
* @see Constant
|
|
||||||
* @throws ClassFormatException if index is invalid
|
* @throws ClassFormatException if index is invalid
|
||||||
|
* @see Constant
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Constant> T getConstant(final int index) throws ClassFormatException {
|
public <T extends Constant> T getConstant(final int index) throws ClassFormatException {
|
||||||
@@ -263,8 +263,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @param tag Tag of expected constant, i.e., its type
|
* @param tag Tag of expected constant, i.e., its type
|
||||||
* @return Constant value
|
* @return Constant value
|
||||||
* @see Constant
|
|
||||||
* @throws ClassFormatException if constant type does not match tag
|
* @throws ClassFormatException if constant type does not match tag
|
||||||
|
* @see Constant
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Constant> T getConstant(final int index, final byte tag) throws ClassFormatException {
|
public <T extends Constant> T getConstant(final int index, final byte tag) throws ClassFormatException {
|
||||||
@@ -277,8 +277,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @param tag Tag of expected constant, i.e., its type
|
* @param tag Tag of expected constant, i.e., its type
|
||||||
* @return Constant value
|
* @return Constant value
|
||||||
* @see Constant
|
|
||||||
* @throws ClassFormatException if constant type does not match tag
|
* @throws ClassFormatException if constant type does not match tag
|
||||||
|
* @see Constant
|
||||||
* @since 6.6.0
|
* @since 6.6.0
|
||||||
*/
|
*/
|
||||||
public <T extends Constant> T getConstant(final int index, final byte tag, final Class<T> castTo) throws ClassFormatException {
|
public <T extends Constant> T getConstant(final int index, final byte tag, final Class<T> castTo) throws ClassFormatException {
|
||||||
@@ -292,12 +292,12 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
/**
|
/**
|
||||||
* Gets constant from constant pool.
|
* Gets constant from constant pool.
|
||||||
*
|
*
|
||||||
* @param <T> A {@link Constant} subclass
|
* @param <T> A {@link Constant} subclass
|
||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @param castTo The {@link Constant} subclass to cast to.
|
* @param castTo The {@link Constant} subclass to cast to.
|
||||||
* @return Constant value
|
* @return Constant value
|
||||||
* @see Constant
|
|
||||||
* @throws ClassFormatException if index is invalid
|
* @throws ClassFormatException if index is invalid
|
||||||
|
* @see Constant
|
||||||
* @since 6.6.0
|
* @since 6.6.0
|
||||||
*/
|
*/
|
||||||
public <T extends Constant> T getConstant(final int index, final Class<T> castTo) throws ClassFormatException {
|
public <T extends Constant> T getConstant(final int index, final Class<T> castTo) throws ClassFormatException {
|
||||||
@@ -311,8 +311,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
// Previous check ensures this won't throw a ClassCastException
|
// Previous check ensures this won't throw a ClassCastException
|
||||||
final T c = castTo.cast(constantPool[index]);
|
final T c = castTo.cast(constantPool[index]);
|
||||||
if (c == null
|
if (c == null
|
||||||
// the 0th element is always null
|
// the 0th element is always null
|
||||||
&& index != 0) {
|
&& index != 0) {
|
||||||
final Constant prev = constantPool[index - 1];
|
final Constant prev = constantPool[index - 1];
|
||||||
if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) {
|
if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) {
|
||||||
throw new ClassFormatException("Constant pool at index " + index + " is null.");
|
throw new ClassFormatException("Constant pool at index " + index + " is null.");
|
||||||
@@ -326,8 +326,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
*
|
*
|
||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @return ConstantInteger value
|
* @return ConstantInteger value
|
||||||
* @see ConstantInteger
|
|
||||||
* @throws ClassFormatException if constant type does not match tag
|
* @throws ClassFormatException if constant type does not match tag
|
||||||
|
* @see ConstantInteger
|
||||||
*/
|
*/
|
||||||
public ConstantInteger getConstantInteger(final int index) {
|
public ConstantInteger getConstantInteger(final int index) {
|
||||||
return getConstant(index, Const.CONSTANT_Integer, ConstantInteger.class);
|
return getConstant(index, Const.CONSTANT_Integer, ConstantInteger.class);
|
||||||
@@ -341,6 +341,13 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
return constantPool;
|
return constantPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param constantPool
|
||||||
|
*/
|
||||||
|
public void setConstantPool(final Constant[] constantPool) {
|
||||||
|
this.constantPool = constantPool;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets string from constant pool and bypass the indirection of 'ConstantClass' and 'ConstantString' objects. I.e. these classes have an index field that
|
* Gets string from constant pool and bypass the indirection of 'ConstantClass' and 'ConstantString' objects. I.e. these classes have an index field that
|
||||||
* points to another entry of the constant pool of type 'ConstantUtf8' which contains the real data.
|
* points to another entry of the constant pool of type 'ConstantUtf8' which contains the real data.
|
||||||
@@ -348,9 +355,9 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @param tag Tag of expected constant, either ConstantClass or ConstantString
|
* @param tag Tag of expected constant, either ConstantClass or ConstantString
|
||||||
* @return Contents of string reference
|
* @return Contents of string reference
|
||||||
|
* @throws IllegalArgumentException if tag is invalid
|
||||||
* @see ConstantClass
|
* @see ConstantClass
|
||||||
* @see ConstantString
|
* @see ConstantString
|
||||||
* @throws IllegalArgumentException if tag is invalid
|
|
||||||
*/
|
*/
|
||||||
public String getConstantString(final int index, final byte tag) throws IllegalArgumentException {
|
public String getConstantString(final int index, final byte tag) throws IllegalArgumentException {
|
||||||
int i;
|
int i;
|
||||||
@@ -360,22 +367,22 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
* subclassing.
|
* subclassing.
|
||||||
*/
|
*/
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case Const.CONSTANT_Class:
|
case Const.CONSTANT_Class:
|
||||||
i = getConstant(index, ConstantClass.class).getNameIndex();
|
i = getConstant(index, ConstantClass.class).getNameIndex();
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_String:
|
case Const.CONSTANT_String:
|
||||||
i = getConstant(index, ConstantString.class).getStringIndex();
|
i = getConstant(index, ConstantString.class).getStringIndex();
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Module:
|
case Const.CONSTANT_Module:
|
||||||
i = getConstant(index, ConstantModule.class).getNameIndex();
|
i = getConstant(index, ConstantModule.class).getNameIndex();
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Package:
|
case Const.CONSTANT_Package:
|
||||||
i = getConstant(index, ConstantPackage.class).getNameIndex();
|
i = getConstant(index, ConstantPackage.class).getNameIndex();
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Utf8:
|
case Const.CONSTANT_Utf8:
|
||||||
return getConstantUtf8(index).getBytes();
|
return getConstantUtf8(index).getBytes();
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("getConstantString called with illegal tag " + tag);
|
throw new IllegalArgumentException("getConstantString called with illegal tag " + tag);
|
||||||
}
|
}
|
||||||
// Finally get the string from the constant pool
|
// Finally get the string from the constant pool
|
||||||
return getConstantUtf8(i).getBytes();
|
return getConstantUtf8(i).getBytes();
|
||||||
@@ -386,8 +393,8 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
*
|
*
|
||||||
* @param index Index in constant pool
|
* @param index Index in constant pool
|
||||||
* @return ConstantUtf8 value
|
* @return ConstantUtf8 value
|
||||||
* @see ConstantUtf8
|
|
||||||
* @throws ClassFormatException if constant type does not match tag
|
* @throws ClassFormatException if constant type does not match tag
|
||||||
|
* @see ConstantUtf8
|
||||||
*/
|
*/
|
||||||
public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException {
|
public ConstantUtf8 getConstantUtf8(final int index) throws ClassFormatException {
|
||||||
return getConstant(index, Const.CONSTANT_Utf8, ConstantUtf8.class);
|
return getConstant(index, Const.CONSTANT_Utf8, ConstantUtf8.class);
|
||||||
@@ -412,13 +419,6 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
constantPool[index] = constant;
|
constantPool[index] = constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param constantPool
|
|
||||||
*/
|
|
||||||
public void setConstantPool(final Constant[] constantPool) {
|
|
||||||
this.constantPool = constantPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
@@ -430,4 +430,164 @@ public class ConstantPool implements Cloneable, Node, Iterable<Constant> {
|
|||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------- haidnorJVM
|
||||||
|
|
||||||
|
public ConstantFieldref getConstantFieldref(int constantFieldrefIndex) {
|
||||||
|
return getConstant(constantFieldrefIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantMethodref getConstantMethodref(int constantMethodrefIndex) {
|
||||||
|
return getConstant(constantMethodrefIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantClass getConstantClass(int constantClassIndex) {
|
||||||
|
return getConstant(constantClassIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantNameAndType getConstantNameAndType(int constantNameAndTypeIndex) {
|
||||||
|
return getConstant(constantNameAndTypeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ConstantClass ---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取长类名, 例如 java/lang/String
|
||||||
|
*/
|
||||||
|
public String constantClass_ClassName(final ConstantClass constantClass) {
|
||||||
|
ConstantUtf8 constantUtf8 = getConstant(constantClass.getNameIndex());
|
||||||
|
return constantUtf8.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取长类名, 例如 java/lang/String
|
||||||
|
*/
|
||||||
|
public String constantClass_ClassName(int constantClassIndex) {
|
||||||
|
ConstantClass constantClass = getConstant(constantClassIndex);
|
||||||
|
return constantClass_ClassName(constantClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ConstantFieldref ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段所处于Java类的类名, 例如 java/lang/String
|
||||||
|
*/
|
||||||
|
public String constantFieldref_ClassName(final ConstantFieldref constantFieldref) {
|
||||||
|
ConstantClass constClass = getConstant(constantFieldref.getClassIndex());
|
||||||
|
return (String) constClass.getConstantValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段所处于Java类的类名, 例如 java/lang/String
|
||||||
|
*/
|
||||||
|
public String constantFieldref_ClassName(int constantFieldrefIndex) {
|
||||||
|
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
|
||||||
|
return constantFieldref_ClassName(constantFieldref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段名称
|
||||||
|
*/
|
||||||
|
public String getFieldName(final ConstantFieldref constantFieldref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(constantFieldref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段名称
|
||||||
|
*/
|
||||||
|
public String getFieldName(int constantFieldrefIndex) {
|
||||||
|
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
|
||||||
|
return getFieldName(constantFieldref);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段类型签名
|
||||||
|
*/
|
||||||
|
public String getFieldSignature(final ConstantFieldref constantFieldref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(constantFieldref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getSignature(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取字段类型签名
|
||||||
|
*/
|
||||||
|
public String getFieldSignature(int constantFieldrefIndex) {
|
||||||
|
ConstantFieldref constantFieldref = getConstantFieldref(constantFieldrefIndex);
|
||||||
|
return getFieldSignature(constantFieldref);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstantMethodref -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法所处于Java类的类名
|
||||||
|
* 名称使用/分割,例如 haidnor/jvm/test/instruction/references/NEW
|
||||||
|
*/
|
||||||
|
public String constantMethodref_ClassName(final ConstantMethodref methodref) {
|
||||||
|
ConstantClass constClass = getConstant(methodref.getClassIndex());
|
||||||
|
return (String) constClass.getConstantValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法名
|
||||||
|
*/
|
||||||
|
public String constantMethodref_MethodName(final ConstantMethodref methodref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法签名
|
||||||
|
*/
|
||||||
|
public String constantMethodref_MethodSignature(final ConstantMethodref methodref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getSignature(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstantInterfaceMethodref -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
public String constantInterfaceMethodref_ClassName(final ConstantInterfaceMethodref methodref) {
|
||||||
|
ConstantClass constClass = getConstant(methodref.getClassIndex());
|
||||||
|
return (String) constClass.getConstantValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法名
|
||||||
|
*/
|
||||||
|
public String constantInterfaceMethodref_MethodName(final ConstantInterfaceMethodref methodref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取方法签名
|
||||||
|
*/
|
||||||
|
public String constantInterfaceMethodref_MethodSignature(final ConstantInterfaceMethodref methodref) {
|
||||||
|
ConstantNameAndType constNameAndType = getConstant(methodref.getNameAndTypeIndex());
|
||||||
|
return constNameAndType.getSignature(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ConstantNameAndType -----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConstantNameAndType
|
||||||
|
*/
|
||||||
|
public ConstantNameAndType constantNameAndType(int constantNameAndTypeIndex) {
|
||||||
|
return getConstant(constantNameAndTypeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String constantNameAndType_name(int constantNameAndTypeIndex) {
|
||||||
|
ConstantNameAndType constantNameAndType = constantNameAndType(constantNameAndTypeIndex);
|
||||||
|
return constantNameAndType.getName(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String constantNameAndType_signature(int constantNameAndTypeIndex) {
|
||||||
|
ConstantNameAndType constantNameAndType = constantNameAndType(constantNameAndTypeIndex);
|
||||||
|
return constantNameAndType.getSignature(this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,47 +57,53 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class ConstantUtf8 extends Constant {
|
public final class ConstantUtf8 extends Constant {
|
||||||
|
|
||||||
private static class Cache {
|
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 boolean BCEL_STATISTICS = Boolean.getBoolean(SYS_PROP_STATISTICS);
|
private static final String SYS_PROP_STATISTICS = "bcel.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO these should perhaps be AtomicInt?
|
// TODO these should perhaps be AtomicInt?
|
||||||
private static volatile int considered;
|
private static volatile int considered;
|
||||||
private static volatile int created;
|
private static volatile int created;
|
||||||
private static volatile int hits;
|
private static volatile int hits;
|
||||||
private static volatile int skipped;
|
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 {
|
static {
|
||||||
if (Cache.BCEL_STATISTICS) {
|
if (Cache.BCEL_STATISTICS) {
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(ConstantUtf8::printStats));
|
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.
|
* 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 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 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,
|
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);
|
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++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,4 +230,29 @@ public final class ConstantUtf8 extends Constant {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString() + "(\"" + Utility.replace(value, "\n", "\\n") + "\")";
|
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;
|
* u2 constantvalue_index;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @see Attribute
|
* @see Attribute
|
||||||
*/
|
*/
|
||||||
public final class ConstantValue extends Attribute {
|
public final class ConstantValue extends Attribute {
|
||||||
@@ -53,9 +54,9 @@ public final class ConstantValue extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Name index in constant pool
|
* @param nameIndex Name index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @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 nameIndex Name index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param constantValueIndex Index in constant pool
|
* @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) {
|
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);
|
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;
|
int i;
|
||||||
// Print constant to string depending on its type
|
// Print constant to string depending on its type
|
||||||
switch (c.getTag()) {
|
switch (c.getTag()) {
|
||||||
case Const.CONSTANT_Long:
|
case Const.CONSTANT_Long:
|
||||||
buf = String.valueOf(((ConstantLong) c).getBytes());
|
buf = String.valueOf(((ConstantLong) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Float:
|
case Const.CONSTANT_Float:
|
||||||
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
buf = String.valueOf(((ConstantFloat) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Double:
|
case Const.CONSTANT_Double:
|
||||||
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
buf = String.valueOf(((ConstantDouble) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_Integer:
|
case Const.CONSTANT_Integer:
|
||||||
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
buf = String.valueOf(((ConstantInteger) c).getBytes());
|
||||||
break;
|
break;
|
||||||
case Const.CONSTANT_String:
|
case Const.CONSTANT_String:
|
||||||
i = ((ConstantString) c).getStringIndex();
|
i = ((ConstantString) c).getStringIndex();
|
||||||
c = super.getConstantPool().getConstantUtf8(i);
|
c = super.getConstantPool().getConstantUtf8(i);
|
||||||
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
buf = "\"" + Utility.convertString(((ConstantUtf8) c).getBytes()) + "\"";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
throw new IllegalStateException("Type of ConstValue invalid: " + c);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,9 +44,9 @@ public final class Deprecated extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param bytes Attribute contents
|
* @param bytes Attribute contents
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public Deprecated(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
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.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class DescendingVisitor implements Visitor {
|
|||||||
private final Stack<Object> stack = new Stack<>();
|
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
|
* @param visitor visitor object to apply to all components
|
||||||
*/
|
*/
|
||||||
public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
|
public DescendingVisitor(final JavaClass clazz, final Visitor visitor) {
|
||||||
@@ -153,7 +153,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.3 */
|
/**
|
||||||
|
* @since 6.3
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantDynamic(final ConstantDynamic obj) {
|
public void visitConstantDynamic(final ConstantDynamic obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -206,7 +208,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.0 */
|
/**
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
|
public void visitConstantMethodHandle(final ConstantMethodHandle obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -221,7 +225,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.0 */
|
/**
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantMethodType(final ConstantMethodType obj) {
|
public void visitConstantMethodType(final ConstantMethodType obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -229,7 +235,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.1 */
|
/**
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantModule(final ConstantModule obj) {
|
public void visitConstantModule(final ConstantModule obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -244,7 +252,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.1 */
|
/**
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitConstantPackage(final ConstantPackage obj) {
|
public void visitConstantPackage(final ConstantPackage obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -408,7 +418,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModule(final Module obj) {
|
public void visitModule(final Module obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -420,7 +432,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleExports(final ModuleExports obj) {
|
public void visitModuleExports(final ModuleExports obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -428,7 +442,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -436,7 +452,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleOpens(final ModuleOpens obj) {
|
public void visitModuleOpens(final ModuleOpens obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -444,7 +462,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModulePackages(final ModulePackages obj) {
|
public void visitModulePackages(final ModulePackages obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -452,7 +472,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleProvides(final ModuleProvides obj) {
|
public void visitModuleProvides(final ModuleProvides obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -460,7 +482,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleRequires(final ModuleRequires obj) {
|
public void visitModuleRequires(final ModuleRequires obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -468,7 +492,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNestHost(final NestHost obj) {
|
public void visitNestHost(final NestHost obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -476,7 +502,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNestMembers(final NestMembers obj) {
|
public void visitNestMembers(final NestMembers obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
@@ -494,7 +522,9 @@ public class DescendingVisitor implements Visitor {
|
|||||||
stack.pop();
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.0 */
|
/**
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
|
public void visitParameterAnnotationEntry(final ParameterAnnotationEntry obj) {
|
||||||
stack.push(obj);
|
stack.push(obj);
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ import java.io.IOException;
|
|||||||
* element_value values[num_values];
|
* element_value values[num_values];
|
||||||
* } array_value;
|
* } array_value;
|
||||||
* } value;
|
* } value;
|
||||||
*}
|
* }
|
||||||
*</pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public abstract class ElementValue {
|
public abstract class ElementValue {
|
||||||
@@ -63,72 +64,6 @@ public abstract class ElementValue {
|
|||||||
public static final byte PRIMITIVE_LONG = 'J';
|
public static final byte PRIMITIVE_LONG = 'J';
|
||||||
public static final byte PRIMITIVE_SHORT = 'S';
|
public static final byte PRIMITIVE_SHORT = 'S';
|
||||||
public static final byte PRIMITIVE_BOOLEAN = 'Z';
|
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
|
* @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;
|
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;
|
public abstract void dump(DataOutputStream dos) throws IOException;
|
||||||
|
|
||||||
/** @since 6.0 */
|
/**
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
final ConstantPool getConstantPool() {
|
final ConstantPool getConstantPool() {
|
||||||
return cpool;
|
return cpool;
|
||||||
}
|
}
|
||||||
@@ -156,7 +158,9 @@ public abstract class ElementValue {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.0 */
|
/**
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
final int getType() {
|
final int getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -235,47 +235,65 @@ public class EmptyVisitor implements Visitor {
|
|||||||
public void visitMethodParameters(final MethodParameters obj) {
|
public void visitMethodParameters(final MethodParameters obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModule(final Module obj) {
|
public void visitModule(final Module obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleExports(final ModuleExports obj) {
|
public void visitModuleExports(final ModuleExports obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleMainClass(final ModuleMainClass obj) {
|
public void visitModuleMainClass(final ModuleMainClass obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleOpens(final ModuleOpens obj) {
|
public void visitModuleOpens(final ModuleOpens obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModulePackages(final ModulePackages obj) {
|
public void visitModulePackages(final ModulePackages obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleProvides(final ModuleProvides obj) {
|
public void visitModuleProvides(final ModuleProvides obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitModuleRequires(final ModuleRequires obj) {
|
public void visitModuleRequires(final ModuleRequires obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNestHost(final NestHost obj) {
|
public void visitNestHost(final NestHost obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 6.4.0 */
|
/**
|
||||||
|
* @since 6.4.0
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void visitNestMembers(final NestMembers obj) {
|
public void visitNestMembers(final NestMembers obj) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
* <p>
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
* <p>
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package haidnor.jvm.bcel.classfile;
|
package haidnor.jvm.bcel.classfile;
|
||||||
|
|
||||||
@@ -81,6 +81,10 @@ public class EnclosingMethod extends Attribute {
|
|||||||
return classIndex;
|
return classIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void setEnclosingClassIndex(final int idx) {
|
||||||
|
classIndex = idx;
|
||||||
|
}
|
||||||
|
|
||||||
public final ConstantNameAndType getEnclosingMethod() {
|
public final ConstantNameAndType getEnclosingMethod() {
|
||||||
if (methodIndex == 0) {
|
if (methodIndex == 0) {
|
||||||
return null;
|
return null;
|
||||||
@@ -92,10 +96,6 @@ public class EnclosingMethod extends Attribute {
|
|||||||
return methodIndex;
|
return methodIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setEnclosingClassIndex(final int idx) {
|
|
||||||
classIndex = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void setEnclosingMethodIndex(final int idx) {
|
public final void setEnclosingMethodIndex(final int idx) {
|
||||||
methodIndex = idx;
|
methodIndex = idx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import java.util.Arrays;
|
|||||||
* u2 exception_index_table[number_of_exceptions];
|
* u2 exception_index_table[number_of_exceptions];
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @see Code
|
* @see Code
|
||||||
*/
|
*/
|
||||||
public final class ExceptionTable extends Attribute {
|
public final class ExceptionTable extends Attribute {
|
||||||
@@ -59,9 +60,9 @@ public final class ExceptionTable extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @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 nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param exceptionIndexTable Table of indices in constant pool
|
* @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) {
|
public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
|
super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool);
|
||||||
@@ -132,6 +133,14 @@ public final class ExceptionTable extends Attribute {
|
|||||||
return exceptionIndexTable;
|
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
|
* @return class names of thrown exceptions
|
||||||
*/
|
*/
|
||||||
@@ -148,14 +157,6 @@ public final class ExceptionTable extends Attribute {
|
|||||||
return exceptionIndexTable == null ? 0 : exceptionIndexTable.length;
|
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.
|
* @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
|
@java.lang.Deprecated
|
||||||
protected int attributes_count; // No. of attributes
|
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
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@java.lang.Deprecated
|
@java.lang.Deprecated
|
||||||
protected ConstantPool constant_pool;
|
protected ConstantPool constant_pool;
|
||||||
|
// @since 6.0
|
||||||
|
private AnnotationEntry[] annotationEntries; // annotations defined on the field or method
|
||||||
private String signatureAttributeString;
|
private String signatureAttributeString;
|
||||||
private boolean searchedForSignatureAttribute;
|
private boolean searchedForSignatureAttribute;
|
||||||
|
|
||||||
@@ -105,14 +102,14 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param accessFlags Access rights of method
|
* @param accessFlags Access rights of method
|
||||||
* @param nameIndex Points to field name in constant pool
|
* @param nameIndex Points to field name in constant pool
|
||||||
* @param signatureIndex Points to encoded signature
|
* @param signatureIndex Points to encoded signature
|
||||||
* @param attributes Collection of attributes
|
* @param attributes Collection of attributes
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
|
protected FieldOrMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes,
|
||||||
final ConstantPool constantPool) {
|
final ConstantPool constantPool) {
|
||||||
super(accessFlags);
|
super(accessFlags);
|
||||||
this.name_index = nameIndex;
|
this.name_index = nameIndex;
|
||||||
this.signature_index = signatureIndex;
|
this.signature_index = signatureIndex;
|
||||||
@@ -173,6 +170,14 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
|||||||
return attributes;
|
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.
|
* @return Constant pool used by this object.
|
||||||
*/
|
*/
|
||||||
@@ -180,6 +185,13 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No
|
|||||||
return constant_pool;
|
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
|
* 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
|
* (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;
|
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)
|
* @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;
|
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.
|
* @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 innerClassIndex Class index in constant pool of inner class
|
||||||
* @param outerClassIndex Class index in constant pool of outer class
|
* @param outerClassIndex Class index in constant pool of outer class
|
||||||
* @param innerNameIndex Name index in constant pool of inner class
|
* @param innerNameIndex Name index in constant pool of inner class
|
||||||
* @param innerAccessFlags Access flags of inner class
|
* @param innerAccessFlags Access flags of inner class
|
||||||
*/
|
*/
|
||||||
public InnerClass(final int innerClassIndex, final int outerClassIndex, final int innerNameIndex, final int innerAccessFlags) {
|
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 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
|
* @param innerAccessFlags access flags for this inner class
|
||||||
*/
|
*/
|
||||||
@@ -138,6 +117,13 @@ public final class InnerClass implements Cloneable, Node {
|
|||||||
this.innerAccessFlags = innerAccessFlags;
|
this.innerAccessFlags = innerAccessFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return class index of inner class.
|
||||||
|
*/
|
||||||
|
public int getInnerClassIndex() {
|
||||||
|
return innerClassIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param innerClassIndex index into the constant pool for this class
|
* @param innerClassIndex index into the constant pool for this class
|
||||||
*/
|
*/
|
||||||
@@ -145,6 +131,13 @@ public final class InnerClass implements Cloneable, Node {
|
|||||||
this.innerClassIndex = innerClassIndex;
|
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
|
* @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;
|
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
|
* @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.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @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 nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param innerClasses array of inner classes attributes
|
* @param innerClasses array of inner classes attributes
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
@@ -127,11 +127,6 @@ public final class InnerClasses extends Attribute implements Iterable<InnerClass
|
|||||||
return innerClasses;
|
return innerClasses;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<InnerClass> iterator() {
|
|
||||||
return Stream.of(innerClasses).iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param innerClasses the array of inner classes
|
* @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;
|
this.innerClasses = innerClasses != null ? innerClasses : EMPTY_INNER_CLASSE_ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<InnerClass> iterator() {
|
||||||
|
return Stream.of(innerClasses).iterator();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ import haidnor.jvm.bcel.util.BCELComparator;
|
|||||||
import haidnor.jvm.bcel.util.ClassQueue;
|
import haidnor.jvm.bcel.util.ClassQueue;
|
||||||
import haidnor.jvm.bcel.util.Repository;
|
import haidnor.jvm.bcel.util.Repository;
|
||||||
import haidnor.jvm.bcel.util.SyntheticRepository;
|
import haidnor.jvm.bcel.util.SyntheticRepository;
|
||||||
|
import haidnor.jvm.classloader.JVMClassLoader;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -71,41 +74,10 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return THIS.getClassName().hashCode();
|
return THIS.getClassName().hashCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* Print debug information depending on 'JavaClass.debug'
|
|
||||||
*/
|
|
||||||
static void Debug(final String str) {
|
|
||||||
if (debug) {
|
|
||||||
System.out.println(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Comparison strategy object
|
|
||||||
*/
|
|
||||||
public static BCELComparator getComparator() {
|
|
||||||
return bcelComparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String indent(final Object obj) {
|
|
||||||
final StringTokenizer tokenizer = new StringTokenizer(obj.toString(), "\n");
|
|
||||||
final StringBuilder buf = new StringBuilder();
|
|
||||||
while (tokenizer.hasMoreTokens()) {
|
|
||||||
buf.append("\t").append(tokenizer.nextToken()).append("\n");
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param comparator Comparison strategy object
|
|
||||||
*/
|
|
||||||
public static void setComparator(final BCELComparator comparator) {
|
|
||||||
bcelComparator = comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String fileName;
|
|
||||||
private final String packageName;
|
private final String packageName;
|
||||||
|
@Getter
|
||||||
|
private final Map<String, JavaField> staticJavaFieldMap = new HashMap<>();
|
||||||
|
private String fileName;
|
||||||
private String sourceFileName = "<Unknown>";
|
private String sourceFileName = "<Unknown>";
|
||||||
private int classNameIndex;
|
private int classNameIndex;
|
||||||
private int superclassNameIndex;
|
private int superclassNameIndex;
|
||||||
@@ -119,36 +91,38 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
private JavaField[] fields; // Fields, i.e., variables of class
|
private JavaField[] fields; // Fields, i.e., variables of class
|
||||||
private JavaMethod[] methods; // methods defined in the class
|
private JavaMethod[] methods; // methods defined in the class
|
||||||
private Attribute[] attributes; // attributes defined in the class
|
private Attribute[] attributes; // attributes defined in the class
|
||||||
|
|
||||||
private AnnotationEntry[] annotations; // annotations defined on the class
|
private AnnotationEntry[] annotations; // annotations defined on the class
|
||||||
private byte source = HEAP; // Generated in memory
|
private byte source = HEAP; // Generated in memory
|
||||||
|
|
||||||
private boolean isAnonymous;
|
private boolean isAnonymous;
|
||||||
|
|
||||||
private boolean isNested;
|
private boolean isNested;
|
||||||
|
|
||||||
private boolean computedNestedTypeStatus;
|
private boolean computedNestedTypeStatus;
|
||||||
|
|
||||||
|
// ---------------------------------------------- haidnorJVM >
|
||||||
/**
|
/**
|
||||||
* In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any
|
* In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any
|
||||||
* better.
|
* better.
|
||||||
*/
|
*/
|
||||||
private transient Repository repository = SyntheticRepository.getInstance();
|
private transient Repository repository = SyntheticRepository.getInstance();
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private JVMClassLoader JVMClassLoader;
|
||||||
|
|
||||||
|
// ---------------------------------------------- haidnorJVM <
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor gets all contents as arguments.
|
* Constructor gets all contents as arguments.
|
||||||
*
|
*
|
||||||
* @param classNameIndex Class name
|
* @param classNameIndex Class name
|
||||||
* @param superclassNameIndex Superclass name
|
* @param superclassNameIndex Superclass name
|
||||||
* @param fileName File name
|
* @param fileName File name
|
||||||
* @param major Major compiler version
|
* @param major Major compiler version
|
||||||
* @param minor Minor compiler version
|
* @param minor Minor compiler version
|
||||||
* @param accessFlags Access rights defined by bit flags
|
* @param accessFlags Access rights defined by bit flags
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @param interfaces Implemented interfaces
|
* @param interfaces Implemented interfaces
|
||||||
* @param fields Class fields
|
* @param fields Class fields
|
||||||
* @param methods Class methods
|
* @param methods Class methods
|
||||||
* @param attributes Class attributes
|
* @param attributes Class attributes
|
||||||
*/
|
*/
|
||||||
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
|
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
|
||||||
final ConstantPool constantPool, final int[] interfaces, final JavaField[] fields, final JavaMethod[] methods, final Attribute[] attributes) {
|
final ConstantPool constantPool, final int[] interfaces, final JavaField[] fields, final JavaMethod[] methods, final Attribute[] attributes) {
|
||||||
@@ -158,19 +132,19 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
/**
|
/**
|
||||||
* Constructor gets all contents as arguments.
|
* Constructor gets all contents as arguments.
|
||||||
*
|
*
|
||||||
* @param classNameIndex Index into constant pool referencing a ConstantClass that represents this class.
|
* @param classNameIndex Index into constant pool referencing a ConstantClass that represents this class.
|
||||||
* @param superclassNameIndex Index into constant pool referencing a ConstantClass that represents this class's
|
* @param superclassNameIndex Index into constant pool referencing a ConstantClass that represents this class's
|
||||||
* superclass.
|
* superclass.
|
||||||
* @param fileName File name
|
* @param fileName File name
|
||||||
* @param major Major compiler version
|
* @param major Major compiler version
|
||||||
* @param minor Minor compiler version
|
* @param minor Minor compiler version
|
||||||
* @param accessFlags Access rights defined by bit flags
|
* @param accessFlags Access rights defined by bit flags
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @param interfaces Implemented interfaces
|
* @param interfaces Implemented interfaces
|
||||||
* @param fields Class fields
|
* @param fields Class fields
|
||||||
* @param methods Class methods
|
* @param methods Class methods
|
||||||
* @param attributes Class attributes
|
* @param attributes Class attributes
|
||||||
* @param source Read from file or generated in memory?
|
* @param source Read from file or generated in memory?
|
||||||
*/
|
*/
|
||||||
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
|
public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags,
|
||||||
final ConstantPool constantPool, int[] interfaces, JavaField[] fields, JavaMethod[] methods, Attribute[] attributes, final byte source) {
|
final ConstantPool constantPool, int[] interfaces, JavaField[] fields, JavaMethod[] methods, Attribute[] attributes, final byte source) {
|
||||||
@@ -229,6 +203,45 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
final String str = constantPool.getConstantString(interfaces[i], Const.CONSTANT_Class);
|
final String str = constantPool.getConstantString(interfaces[i], Const.CONSTANT_Class);
|
||||||
interfaceNames[i] = Utility.compactClassName(str, false);
|
interfaceNames[i] = Utility.compactClassName(str, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化静态字段
|
||||||
|
for (JavaField field : getFields()) {
|
||||||
|
if (field.isStatic()) {
|
||||||
|
staticJavaFieldMap.put(field.getName(), field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print debug information depending on 'JavaClass.debug'
|
||||||
|
*/
|
||||||
|
static void Debug(final String str) {
|
||||||
|
if (debug) {
|
||||||
|
System.out.println(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 static String indent(final Object obj) {
|
||||||
|
final StringTokenizer tokenizer = new StringTokenizer(obj.toString(), "\n");
|
||||||
|
final StringBuilder buf = new StringBuilder();
|
||||||
|
while (tokenizer.hasMoreTokens()) {
|
||||||
|
buf.append("\t").append(tokenizer.nextToken()).append("\n");
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -258,7 +271,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
}
|
}
|
||||||
for (final Attribute attribute : this.attributes) {
|
for (final Attribute attribute : this.attributes) {
|
||||||
if (attribute instanceof InnerClasses) {
|
if (attribute instanceof InnerClasses) {
|
||||||
((InnerClasses) attribute).forEach(innerClass -> {
|
((InnerClasses) attribute).forEach(innerClass -> {
|
||||||
boolean innerClassAttributeRefersToMe = false;
|
boolean innerClassAttributeRefersToMe = false;
|
||||||
String innerClassName = constantPool.getConstantString(innerClass.getInnerClassIndex(), Const.CONSTANT_Class);
|
String innerClassName = constantPool.getConstantString(innerClass.getInnerClassIndex(), Const.CONSTANT_Class);
|
||||||
innerClassName = Utility.compactClassName(innerClassName, false);
|
innerClassName = Utility.compactClassName(innerClassName, false);
|
||||||
@@ -429,6 +442,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param attributes .
|
||||||
|
*/
|
||||||
|
public void setAttributes(final Attribute[] attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return class in binary format
|
* @return class in binary format
|
||||||
*/
|
*/
|
||||||
@@ -449,6 +469,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param className .
|
||||||
|
*/
|
||||||
|
public void setClassName(final String className) {
|
||||||
|
this.className = className;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Class name index.
|
* @return Class name index.
|
||||||
*/
|
*/
|
||||||
@@ -456,6 +483,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return classNameIndex;
|
return classNameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param classNameIndex .
|
||||||
|
*/
|
||||||
|
public void setClassNameIndex(final int classNameIndex) {
|
||||||
|
this.classNameIndex = classNameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Constant pool.
|
* @return Constant pool.
|
||||||
*/
|
*/
|
||||||
@@ -463,14 +497,28 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return constantPool;
|
return constantPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param constantPool .
|
||||||
|
*/
|
||||||
|
public void setConstantPool(final ConstantPool constantPool) {
|
||||||
|
this.constantPool = constantPool;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Fields, i.e., variables of the class. Like the JVM spec mandates for the classfile format, these fields are
|
* @return Fields, i.e., variables of the class. Like the JVM spec mandates for the classfile format, these fields are
|
||||||
* those specific to this class, and not those of the superclass or superinterfaces.
|
* those specific to this class, and not those of the superclass or superinterfaces.
|
||||||
*/
|
*/
|
||||||
public JavaField[] getFields() {
|
public JavaField[] getFields() {
|
||||||
return fields;
|
return fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fields .
|
||||||
|
*/
|
||||||
|
public void setFields(final JavaField[] fields) {
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return File name of class, aka SourceFile attribute value
|
* @return File name of class, aka SourceFile attribute value
|
||||||
*/
|
*/
|
||||||
@@ -478,6 +526,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set File name of class, aka SourceFile attribute value
|
||||||
|
*/
|
||||||
|
public void setFileName(final String fileName) {
|
||||||
|
this.fileName = fileName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Indices in constant pool of implemented interfaces.
|
* @return Indices in constant pool of implemented interfaces.
|
||||||
*/
|
*/
|
||||||
@@ -492,6 +547,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return interfaceNames;
|
return interfaceNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param interfaceNames .
|
||||||
|
*/
|
||||||
|
public void setInterfaceNames(final String[] interfaceNames) {
|
||||||
|
this.interfaceNames = interfaceNames;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get interfaces directly implemented by this JavaClass.
|
* Get interfaces directly implemented by this JavaClass.
|
||||||
*
|
*
|
||||||
@@ -506,6 +568,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param interfaces .
|
||||||
|
*/
|
||||||
|
public void setInterfaces(final int[] interfaces) {
|
||||||
|
this.interfaces = interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Major number of class file version.
|
* @return Major number of class file version.
|
||||||
*/
|
*/
|
||||||
@@ -513,6 +582,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return major;
|
return major;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param major .
|
||||||
|
*/
|
||||||
|
public void setMajor(final int major) {
|
||||||
|
this.major = major;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return A {@link JavaMethod} corresponding to java.lang.reflect.Method if any
|
* @return A {@link JavaMethod} corresponding to java.lang.reflect.Method if any
|
||||||
*/
|
*/
|
||||||
@@ -532,6 +608,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return methods;
|
return methods;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param methods .
|
||||||
|
*/
|
||||||
|
public void setMethods(final JavaMethod[] methods) {
|
||||||
|
this.methods = methods;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Minor number of class file version.
|
* @return Minor number of class file version.
|
||||||
*/
|
*/
|
||||||
@@ -539,6 +622,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return minor;
|
return minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param minor .
|
||||||
|
*/
|
||||||
|
public void setMinor(final int minor) {
|
||||||
|
this.minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Package name.
|
* @return Package name.
|
||||||
*/
|
*/
|
||||||
@@ -554,6 +644,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done.
|
||||||
|
*/
|
||||||
|
public void setRepository(final Repository repository) { // TODO make protected?
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return returns either HEAP (generated), FILE, or ZIP
|
* @return returns either HEAP (generated), FILE, or ZIP
|
||||||
*/
|
*/
|
||||||
@@ -568,6 +665,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return sourceFileName;
|
return sourceFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set absolute path to file this class was read from.
|
||||||
|
*/
|
||||||
|
public void setSourceFileName(final String sourceFileName) {
|
||||||
|
this.sourceFileName = sourceFileName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the source file path including the package path.
|
* Gets the source file path including the package path.
|
||||||
*
|
*
|
||||||
@@ -618,6 +722,13 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return superclassName;
|
return superclassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param superclassName .
|
||||||
|
*/
|
||||||
|
public void setSuperclassName(final String superclassName) {
|
||||||
|
this.superclassName = superclassName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Class name index.
|
* @return Class name index.
|
||||||
*/
|
*/
|
||||||
@@ -625,6 +736,17 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return superclassNameIndex;
|
return superclassNameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param superclassNameIndex .
|
||||||
|
*/
|
||||||
|
public void setSuperclassNameIndex(final int superclassNameIndex) {
|
||||||
|
this.superclassNameIndex = superclassNameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JavaField getStaticField(String filedName) {
|
||||||
|
return staticJavaFieldMap.get(filedName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
|
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
|
||||||
*
|
*
|
||||||
@@ -700,111 +822,6 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
return (super.getAccessFlags() & Const.ACC_SUPER) != 0;
|
return (super.getAccessFlags() & Const.ACC_SUPER) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param attributes .
|
|
||||||
*/
|
|
||||||
public void setAttributes(final Attribute[] attributes) {
|
|
||||||
this.attributes = attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param className .
|
|
||||||
*/
|
|
||||||
public void setClassName(final String className) {
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param classNameIndex .
|
|
||||||
*/
|
|
||||||
public void setClassNameIndex(final int classNameIndex) {
|
|
||||||
this.classNameIndex = classNameIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param constantPool .
|
|
||||||
*/
|
|
||||||
public void setConstantPool(final ConstantPool constantPool) {
|
|
||||||
this.constantPool = constantPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param fields .
|
|
||||||
*/
|
|
||||||
public void setFields(final JavaField[] fields) {
|
|
||||||
this.fields = fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set File name of class, aka SourceFile attribute value
|
|
||||||
*/
|
|
||||||
public void setFileName(final String fileName) {
|
|
||||||
this.fileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param interfaceNames .
|
|
||||||
*/
|
|
||||||
public void setInterfaceNames(final String[] interfaceNames) {
|
|
||||||
this.interfaceNames = interfaceNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param interfaces .
|
|
||||||
*/
|
|
||||||
public void setInterfaces(final int[] interfaces) {
|
|
||||||
this.interfaces = interfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param major .
|
|
||||||
*/
|
|
||||||
public void setMajor(final int major) {
|
|
||||||
this.major = major;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param methods .
|
|
||||||
*/
|
|
||||||
public void setMethods(final JavaMethod[] methods) {
|
|
||||||
this.methods = methods;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param minor .
|
|
||||||
*/
|
|
||||||
public void setMinor(final int minor) {
|
|
||||||
this.minor = minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the ClassRepository which loaded the JavaClass. Should be called immediately after parsing is done.
|
|
||||||
*/
|
|
||||||
public void setRepository(final Repository repository) { // TODO make protected?
|
|
||||||
this.repository = repository;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set absolute path to file this class was read from.
|
|
||||||
*/
|
|
||||||
public void setSourceFileName(final String sourceFileName) {
|
|
||||||
this.sourceFileName = sourceFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param superclassName .
|
|
||||||
*/
|
|
||||||
public void setSuperclassName(final String superclassName) {
|
|
||||||
this.superclassName = superclassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param superclassNameIndex .
|
|
||||||
*/
|
|
||||||
public void setSuperclassNameIndex(final int superclassNameIndex) {
|
|
||||||
this.superclassNameIndex = superclassNameIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representing class contents.
|
* @return String representing class contents.
|
||||||
*/
|
*/
|
||||||
@@ -814,7 +831,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
access = access.isEmpty() ? "" : access + " ";
|
access = access.isEmpty() ? "" : access + " ";
|
||||||
final StringBuilder buf = new StringBuilder(128);
|
final StringBuilder buf = new StringBuilder(128);
|
||||||
buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append(className).append(" extends ")
|
buf.append(access).append(Utility.classOrInterface(super.getAccessFlags())).append(" ").append(className).append(" extends ")
|
||||||
.append(Utility.compactClassName(superclassName, false)).append('\n');
|
.append(Utility.compactClassName(superclassName, false)).append('\n');
|
||||||
final int size = interfaces.length;
|
final int size = interfaces.length;
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
buf.append("implements\t\t");
|
buf.append("implements\t\t");
|
||||||
@@ -859,4 +876,20 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl
|
|||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------- haidnorJVM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 main 方法
|
||||||
|
*/
|
||||||
|
public JavaMethod getMainMethod() {
|
||||||
|
for (JavaMethod javaMethod : getMethods()) {
|
||||||
|
if (javaMethod.toString().startsWith("public static void main(String[] args)")) {
|
||||||
|
return javaMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
* This class represents the field info structure, i.e., the representation for a variable in the class. See JVM
|
||||||
* specification for details.
|
* specification for details.
|
||||||
*/
|
*/
|
||||||
public final class JavaField extends FieldOrMethod {
|
public class JavaField extends FieldOrMethod {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty array constant.
|
* Empty array constant.
|
||||||
@@ -36,7 +36,10 @@ public final class JavaField extends FieldOrMethod {
|
|||||||
* @since 6.6.0
|
* @since 6.6.0
|
||||||
*/
|
*/
|
||||||
public static final JavaField[] EMPTY_ARRAY = {};
|
public static final JavaField[] EMPTY_ARRAY = {};
|
||||||
|
/**
|
||||||
|
* Empty array.
|
||||||
|
*/
|
||||||
|
static final JavaField[] EMPTY_FIELD_ARRAY = {};
|
||||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -52,25 +55,14 @@ public final class JavaField extends FieldOrMethod {
|
|||||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
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() {
|
private Object value;
|
||||||
return bcelComparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param comparator Comparison strategy object
|
|
||||||
*/
|
|
||||||
public static void setComparator(final BCELComparator comparator) {
|
|
||||||
bcelComparator = comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct object from file stream.
|
* Construct object from file stream.
|
||||||
@@ -92,16 +84,30 @@ public final class JavaField extends FieldOrMethod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param accessFlags Access rights of field
|
* @param accessFlags Access rights of field
|
||||||
* @param nameIndex Points to field name in constant pool
|
* @param nameIndex Points to field name in constant pool
|
||||||
* @param signatureIndex Points to encoded signature
|
* @param signatureIndex Points to encoded signature
|
||||||
* @param attributes Collection of attributes
|
* @param attributes Collection of attributes
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public JavaField(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
public JavaField(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||||
super(accessFlags, nameIndex, signatureIndex, attributes, 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.
|
* 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.
|
* 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());
|
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
|
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
|
||||||
* signature.
|
* 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
|
* 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.
|
* 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.
|
* Empty array constant.
|
||||||
@@ -35,7 +35,10 @@ public final class JavaMethod extends FieldOrMethod {
|
|||||||
* @since 6.6.0
|
* @since 6.6.0
|
||||||
*/
|
*/
|
||||||
public static final JavaMethod[] EMPTY_ARRAY = {};
|
public static final JavaMethod[] EMPTY_ARRAY = {};
|
||||||
|
/**
|
||||||
|
* Empty array.
|
||||||
|
*/
|
||||||
|
static final JavaMethod[] EMPTY_METHOD_ARRAY = {};
|
||||||
private static BCELComparator bcelComparator = new BCELComparator() {
|
private static BCELComparator bcelComparator = new BCELComparator() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -51,26 +54,6 @@ public final class JavaMethod extends FieldOrMethod {
|
|||||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
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
|
// annotations defined on the parameters of a method
|
||||||
private ParameterAnnotationEntry[] parameterAnnotationEntries;
|
private ParameterAnnotationEntry[] parameterAnnotationEntries;
|
||||||
|
|
||||||
@@ -84,7 +67,7 @@ public final class JavaMethod extends FieldOrMethod {
|
|||||||
* Construct object from file stream.
|
* Construct object from file stream.
|
||||||
*
|
*
|
||||||
* @param file Input 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
|
* @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 {
|
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 accessFlags Access rights of method
|
||||||
* @param nameIndex Points to field name in constant pool
|
* @param nameIndex Points to field name in constant pool
|
||||||
* @param signatureIndex Points to encoded signature
|
* @param signatureIndex Points to encoded signature
|
||||||
* @param attributes Collection of attributes
|
* @param attributes Collection of attributes
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public JavaMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
public JavaMethod(final int accessFlags, final int nameIndex, final int signatureIndex, final Attribute[] attributes, final ConstantPool constantPool) {
|
||||||
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
super(accessFlags, nameIndex, signatureIndex, attributes, constantPool);
|
||||||
@@ -112,6 +95,20 @@ public final class JavaMethod extends FieldOrMethod {
|
|||||||
super(c);
|
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.
|
* 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.
|
* 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
|
* @return ExceptionTable attribute of method, if any, i.e., list all exceptions the method may throw not exception
|
||||||
* handlers!
|
* handlers!
|
||||||
*/
|
*/
|
||||||
public ExceptionTable getExceptionTable() {
|
public ExceptionTable getExceptionTable() {
|
||||||
for (final Attribute attribute : super.getAttributes()) {
|
for (final Attribute attribute : super.getAttributes()) {
|
||||||
|
|||||||
@@ -32,10 +32,14 @@ public final class LineNumber implements Cloneable, Node {
|
|||||||
|
|
||||||
static final LineNumber[] EMPTY_ARRAY = {};
|
static final LineNumber[] EMPTY_ARRAY = {};
|
||||||
|
|
||||||
/** Program Counter (PC) corresponds to line */
|
/**
|
||||||
|
* Program Counter (PC) corresponds to line
|
||||||
|
*/
|
||||||
private int startPc;
|
private int startPc;
|
||||||
|
|
||||||
/** number in source file */
|
/**
|
||||||
|
* number in source file
|
||||||
|
*/
|
||||||
private int lineNumber;
|
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
|
* @param lineNumber line number in source file
|
||||||
*/
|
*/
|
||||||
public LineNumber(final int startPc, final int lineNumber) {
|
public LineNumber(final int startPc, final int lineNumber) {
|
||||||
@@ -107,13 +111,6 @@ public final class LineNumber implements Cloneable, Node {
|
|||||||
return lineNumber & 0xffff;
|
return lineNumber & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PC in code
|
|
||||||
*/
|
|
||||||
public int getStartPC() {
|
|
||||||
return startPc & 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param lineNumber the source line number
|
* @param lineNumber the source line number
|
||||||
*/
|
*/
|
||||||
@@ -121,6 +118,13 @@ public final class LineNumber implements Cloneable, Node {
|
|||||||
this.lineNumber = (short) lineNumber;
|
this.lineNumber = (short) lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PC in code
|
||||||
|
*/
|
||||||
|
public int getStartPC() {
|
||||||
|
return startPc & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param startPc the pc for this line number
|
* @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.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index of name
|
* @param nameIndex Index of name
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O Exception occurs in readUnsignedShort
|
* @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;
|
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.
|
* 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();
|
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.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -36,35 +36,28 @@ import java.io.IOException;
|
|||||||
public final class LocalVariable implements Cloneable, Node {
|
public final class LocalVariable implements Cloneable, Node {
|
||||||
|
|
||||||
static final LocalVariable[] EMPTY_ARRAY = {};
|
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.
|
* Never changes; used to match up with LocalVariableTypeTable entries.
|
||||||
*/
|
*/
|
||||||
private final int origIndex;
|
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.
|
* Constructs object from file stream.
|
||||||
@@ -164,6 +157,13 @@ public final class LocalVariable implements Cloneable, Node {
|
|||||||
return constantPool;
|
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
|
* @return index of register where variable is stored
|
||||||
*/
|
*/
|
||||||
@@ -171,6 +171,13 @@ public final class LocalVariable implements Cloneable, Node {
|
|||||||
return index;
|
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()
|
* @return Variable is valid within getStartPC() .. getStartPC()+getLength()
|
||||||
*/
|
*/
|
||||||
@@ -178,6 +185,13 @@ public final class LocalVariable implements Cloneable, Node {
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param length the length of this local variable
|
||||||
|
*/
|
||||||
|
public void setLength(final int length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Variable name.
|
* @return Variable name.
|
||||||
*/
|
*/
|
||||||
@@ -192,6 +206,13 @@ public final class LocalVariable implements Cloneable, Node {
|
|||||||
return nameIndex;
|
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
|
* @return index of register where variable was originally stored
|
||||||
*/
|
*/
|
||||||
@@ -213,41 +234,6 @@ public final class LocalVariable implements Cloneable, Node {
|
|||||||
return signatureIndex;
|
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
|
* @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;
|
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.
|
* @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.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @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 nameIndex Index in constant pool to 'LocalVariableTable'
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param localVariableTable Table of local variables
|
* @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) {
|
public LocalVariableTable(final int nameIndex, final int length, final LocalVariable[] localVariableTable, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_LOCAL_VARIABLE_TABLE, nameIndex, length, 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
|
* @param index the variable slot
|
||||||
*
|
|
||||||
* @return the first LocalVariable that matches the slot or null if not found
|
* @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)
|
* @deprecated since 5.2 because multiple variables can share the same slot, use getLocalVariable(int index, int pc)
|
||||||
* instead.
|
* instead.
|
||||||
*/
|
*/
|
||||||
@java.lang.Deprecated
|
@java.lang.Deprecated
|
||||||
public final LocalVariable getLocalVariable(final int index) {
|
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 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
|
* @return the LocalVariable that matches or null if not found
|
||||||
*/
|
*/
|
||||||
public final LocalVariable getLocalVariable(final int index, final int pc) {
|
public final LocalVariable getLocalVariable(final int index, final int pc) {
|
||||||
@@ -161,6 +156,10 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
|||||||
return localVariableTable;
|
return localVariableTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
||||||
|
this.localVariableTable = localVariableTable;
|
||||||
|
}
|
||||||
|
|
||||||
public final int getTableLength() {
|
public final int getTableLength() {
|
||||||
return localVariableTable == null ? 0 : localVariableTable.length;
|
return localVariableTable == null ? 0 : localVariableTable.length;
|
||||||
}
|
}
|
||||||
@@ -170,10 +169,6 @@ public class LocalVariableTable extends Attribute implements Iterable<LocalVaria
|
|||||||
return Stream.of(localVariableTable).iterator();
|
return Stream.of(localVariableTable).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setLocalVariableTable(final LocalVariable[] localVariableTable) {
|
|
||||||
this.localVariableTable = localVariableTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
/**
|
/**
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
* this work for additional information regarding copyright ownership.
|
* this work for additional information regarding copyright ownership.
|
||||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
* 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 not use this file except in compliance with
|
||||||
* the License. You may obtain a copy of the License at
|
* the License. You may obtain a copy of the License at
|
||||||
*
|
* <p>
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
* <p>
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package haidnor.jvm.bcel.classfile;
|
package haidnor.jvm.bcel.classfile;
|
||||||
|
|||||||
@@ -27,15 +27,19 @@ import java.io.IOException;
|
|||||||
* Entry of the parameters table.
|
* 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 :
|
* @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
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public class MethodParameter implements Cloneable, Node {
|
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;
|
private int nameIndex;
|
||||||
|
|
||||||
/** The access flags */
|
/**
|
||||||
|
* The access flags
|
||||||
|
*/
|
||||||
private int accessFlags;
|
private int accessFlags;
|
||||||
|
|
||||||
public MethodParameter() {
|
public MethodParameter() {
|
||||||
@@ -45,7 +49,7 @@ public class MethodParameter implements Cloneable, Node {
|
|||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param input 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
|
* @throws ClassFormatException if a class is malformed or cannot be interpreted as a class file
|
||||||
*/
|
*/
|
||||||
MethodParameter(final DataInput input) throws IOException {
|
MethodParameter(final DataInput input) throws IOException {
|
||||||
@@ -85,10 +89,18 @@ public class MethodParameter implements Cloneable, Node {
|
|||||||
return accessFlags;
|
return accessFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAccessFlags(final int accessFlags) {
|
||||||
|
this.accessFlags = accessFlags;
|
||||||
|
}
|
||||||
|
|
||||||
public int getNameIndex() {
|
public int getNameIndex() {
|
||||||
return nameIndex;
|
return nameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNameIndex(final int nameIndex) {
|
||||||
|
this.nameIndex = nameIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the parameter.
|
* Returns the name of the parameter.
|
||||||
*/
|
*/
|
||||||
@@ -110,12 +122,4 @@ public class MethodParameter implements Cloneable, Node {
|
|||||||
public boolean isSynthetic() {
|
public boolean isSynthetic() {
|
||||||
return (accessFlags & Const.ACC_SYNTHETIC) != 0;
|
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.
|
* 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 :
|
* @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
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
public class MethodParameters extends Attribute implements Iterable<MethodParameter> {
|
public class MethodParameters extends Attribute implements Iterable<MethodParameter> {
|
||||||
@@ -86,12 +86,12 @@ public class MethodParameters extends Attribute implements Iterable<MethodParame
|
|||||||
return parameters;
|
return parameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setParameters(final MethodParameter[] parameters) {
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<MethodParameter> iterator() {
|
public Iterator<MethodParameter> iterator() {
|
||||||
return Stream.of(parameters).iterator();
|
return Stream.of(parameters).iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParameters(final MethodParameter[] parameters) {
|
|
||||||
this.parameters = parameters;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,20 +43,19 @@ public final class Module extends Attribute {
|
|||||||
private final int moduleNameIndex;
|
private final int moduleNameIndex;
|
||||||
private final int moduleFlags;
|
private final int moduleFlags;
|
||||||
private final int moduleVersionIndex;
|
private final int moduleVersionIndex;
|
||||||
|
private final int usesCount;
|
||||||
|
private final int[] usesIndex;
|
||||||
private ModuleRequires[] requiresTable;
|
private ModuleRequires[] requiresTable;
|
||||||
private ModuleExports[] exportsTable;
|
private ModuleExports[] exportsTable;
|
||||||
private ModuleOpens[] opensTable;
|
private ModuleOpens[] opensTable;
|
||||||
private final int usesCount;
|
|
||||||
private final int[] usesIndex;
|
|
||||||
private ModuleProvides[] providesTable;
|
private ModuleProvides[] providesTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ public final class ModuleMainClass extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -49,10 +49,10 @@ public final class ModuleMainClass extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param mainClassIndex Host class index
|
* @param mainClassIndex Host class index
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public ModuleMainClass(final int nameIndex, final int length, final int mainClassIndex, final ConstantPool constantPool) {
|
public ModuleMainClass(final int nameIndex, final int length, final int mainClassIndex, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ public final class ModulePackages extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -55,10 +55,10 @@ public final class ModulePackages extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param packageIndexTable Table of indices in constant pool
|
* @param packageIndexTable Table of indices in constant pool
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) {
|
public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool);
|
super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool);
|
||||||
@@ -129,6 +129,13 @@ public final class ModulePackages extends Attribute {
|
|||||||
return packageIndexTable;
|
return packageIndexTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length.
|
||||||
|
*/
|
||||||
|
public void setPackageIndexTable(final int[] packageIndexTable) {
|
||||||
|
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : ArrayUtils.EMPTY_INT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string array of package names
|
* @return string array of package names
|
||||||
*/
|
*/
|
||||||
@@ -138,13 +145,6 @@ public final class ModulePackages extends Attribute {
|
|||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length.
|
|
||||||
*/
|
|
||||||
public void setPackageIndexTable(final int[] packageIndexTable) {
|
|
||||||
this.packageIndexTable = packageIndexTable != null ? packageIndexTable : ArrayUtils.EMPTY_INT_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation, i.e., a list of packages.
|
* @return String representation, i.e., a list of packages.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ public final class NestHost extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Constructs object from input stream.
|
* Constructs object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -49,10 +49,10 @@ public final class NestHost extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param hostClassIndex Host class index
|
* @param hostClassIndex Host class index
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public NestHost(final int nameIndex, final int length, final int hostClassIndex, final ConstantPool constantPool) {
|
public NestHost(final int nameIndex, final int length, final int hostClassIndex, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool);
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ public final class NestMembers extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -56,9 +56,9 @@ public final class NestMembers extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param classes Table of indices in constant pool
|
* @param classes Table of indices in constant pool
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) {
|
public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) {
|
||||||
@@ -123,6 +123,13 @@ public final class NestMembers extends Attribute {
|
|||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param classes the list of class indexes Also redefines number_of_classes according to table length.
|
||||||
|
*/
|
||||||
|
public void setClasses(final int[] classes) {
|
||||||
|
this.classes = classes != null ? classes : ArrayUtils.EMPTY_INT_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string array of class names
|
* @return string array of class names
|
||||||
*/
|
*/
|
||||||
@@ -139,13 +146,6 @@ public final class NestMembers extends Attribute {
|
|||||||
return classes.length;
|
return classes.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param classes the list of class indexes Also redefines number_of_classes according to table length.
|
|
||||||
*/
|
|
||||||
public void setClasses(final int[] classes) {
|
|
||||||
this.classes = classes != null ? classes : ArrayUtils.EMPTY_INT_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation, i.e., a list of classes.
|
* @return String representation, i.e., a list of classes.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ public final class PMGClass extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -46,11 +46,11 @@ public final class PMGClass extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param pmgIndex index in constant pool for source file name
|
* @param pmgIndex index in constant pool for source file name
|
||||||
* @param pmgClassIndex Index in constant pool to CONSTANT_Utf8
|
* @param pmgClassIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public PMGClass(final int nameIndex, final int length, final int pmgIndex, final int pmgClassIndex, final ConstantPool constantPool) {
|
public PMGClass(final int nameIndex, final int length, final int pmgIndex, final int pmgClassIndex, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_PMG, nameIndex, length, constantPool);
|
super(Const.ATTR_PMG, nameIndex, length, constantPool);
|
||||||
@@ -107,6 +107,13 @@ public final class PMGClass extends Attribute {
|
|||||||
return pmgClassIndex;
|
return pmgClassIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pmgClassIndex
|
||||||
|
*/
|
||||||
|
public void setPMGClassIndex(final int pmgClassIndex) {
|
||||||
|
this.pmgClassIndex = pmgClassIndex;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return PMG class name.
|
* @return PMG class name.
|
||||||
*/
|
*/
|
||||||
@@ -121,20 +128,6 @@ public final class PMGClass extends Attribute {
|
|||||||
return pmgIndex;
|
return pmgIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return PMG name.
|
|
||||||
*/
|
|
||||||
public String getPMGName() {
|
|
||||||
return super.getConstantPool().getConstantUtf8(pmgIndex).getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pmgClassIndex
|
|
||||||
*/
|
|
||||||
public void setPMGClassIndex(final int pmgClassIndex) {
|
|
||||||
this.pmgClassIndex = pmgClassIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pmgIndex
|
* @param pmgIndex
|
||||||
*/
|
*/
|
||||||
@@ -142,6 +135,13 @@ public final class PMGClass extends Attribute {
|
|||||||
this.pmgIndex = pmgIndex;
|
this.pmgIndex = pmgIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PMG name.
|
||||||
|
*/
|
||||||
|
public String getPMGName() {
|
||||||
|
return super.getConstantPool().getConstantUtf8(pmgIndex).getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation
|
* @return String representation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,19 +31,6 @@ import java.util.List;
|
|||||||
public class ParameterAnnotationEntry implements Node {
|
public class ParameterAnnotationEntry implements Node {
|
||||||
|
|
||||||
static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
|
static final ParameterAnnotationEntry[] EMPTY_ARRAY = {};
|
||||||
|
|
||||||
public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
|
|
||||||
// Find attributes that contain parameter annotation data
|
|
||||||
final List<ParameterAnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
|
||||||
for (final Attribute attribute : attrs) {
|
|
||||||
if (attribute instanceof ParameterAnnotations) {
|
|
||||||
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute;
|
|
||||||
Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AnnotationEntry[] annotationTable;
|
private final AnnotationEntry[] annotationTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,6 +48,18 @@ public class ParameterAnnotationEntry implements Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) {
|
||||||
|
// Find attributes that contain parameter annotation data
|
||||||
|
final List<ParameterAnnotationEntry> accumulatedAnnotations = new ArrayList<>(attrs.length);
|
||||||
|
for (final Attribute attribute : attrs) {
|
||||||
|
if (attribute instanceof ParameterAnnotations) {
|
||||||
|
final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute;
|
||||||
|
Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
* 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.
|
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||||
|
|||||||
@@ -29,18 +29,20 @@ import java.util.stream.Stream;
|
|||||||
*/
|
*/
|
||||||
public abstract class ParameterAnnotations extends Attribute implements Iterable<ParameterAnnotationEntry> {
|
public abstract class ParameterAnnotations extends Attribute implements Iterable<ParameterAnnotationEntry> {
|
||||||
|
|
||||||
/** Table of parameter annotations */
|
/**
|
||||||
|
* Table of parameter annotations
|
||||||
|
*/
|
||||||
private ParameterAnnotationEntry[] parameterAnnotationTable;
|
private ParameterAnnotationEntry[] parameterAnnotationTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parameterAnnotationType the subclass type of the parameter annotation
|
* @param parameterAnnotationType the subclass type of the parameter annotation
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
this(parameterAnnotationType, nameIndex, length, (ParameterAnnotationEntry[]) null, constantPool);
|
this(parameterAnnotationType, nameIndex, length, (ParameterAnnotationEntry[]) null, constantPool);
|
||||||
final int numParameters = input.readUnsignedByte();
|
final int numParameters = input.readUnsignedByte();
|
||||||
parameterAnnotationTable = new ParameterAnnotationEntry[numParameters];
|
parameterAnnotationTable = new ParameterAnnotationEntry[numParameters];
|
||||||
@@ -50,14 +52,14 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parameterAnnotationType the subclass type of the parameter annotation
|
* @param parameterAnnotationType the subclass type of the parameter annotation
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param parameterAnnotationTable the actual parameter annotations
|
* @param parameterAnnotationTable the actual parameter annotations
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length,
|
public ParameterAnnotations(final byte parameterAnnotationType, final int nameIndex, final int length,
|
||||||
final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) {
|
final ParameterAnnotationEntry[] parameterAnnotationTable, final ConstantPool constantPool) {
|
||||||
super(parameterAnnotationType, nameIndex, length, constantPool);
|
super(parameterAnnotationType, nameIndex, length, constantPool);
|
||||||
this.parameterAnnotationTable = parameterAnnotationTable;
|
this.parameterAnnotationTable = parameterAnnotationTable;
|
||||||
}
|
}
|
||||||
@@ -106,15 +108,15 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable
|
|||||||
return parameterAnnotationTable;
|
return parameterAnnotationTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<ParameterAnnotationEntry> iterator() {
|
|
||||||
return Stream.of(parameterAnnotationTable).iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param parameterAnnotationTable the entries to set in this parameter annotation
|
* @param parameterAnnotationTable the entries to set in this parameter annotation
|
||||||
*/
|
*/
|
||||||
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) {
|
public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) {
|
||||||
this.parameterAnnotationTable = parameterAnnotationTable;
|
this.parameterAnnotationTable = parameterAnnotationTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ParameterAnnotationEntry> iterator() {
|
||||||
|
return Stream.of(parameterAnnotationTable).iterator();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ import java.io.IOException;
|
|||||||
public class RuntimeInvisibleAnnotations extends Annotations {
|
public class RuntimeInvisibleAnnotations extends Annotations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ import java.io.IOException;
|
|||||||
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
|
public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||||
*/
|
*/
|
||||||
public RuntimeInvisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
public RuntimeInvisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
super(Const.ATTR_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ import java.io.IOException;
|
|||||||
public class RuntimeVisibleAnnotations extends Annotations {
|
public class RuntimeVisibleAnnotations extends Annotations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -29,14 +29,14 @@ import java.io.IOException;
|
|||||||
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
|
public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index pointing to the name <em>Code</em>
|
* @param nameIndex Index pointing to the name <em>Code</em>
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
* @throws IOException Thrown when an I/O exception of some sort has occurred.
|
||||||
*/
|
*/
|
||||||
public RuntimeVisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
public RuntimeVisibleParameterAnnotations(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
super(Const.ATTR_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, nameIndex, length, input, constantPool);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,24 +33,42 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
public final class Signature extends Attribute {
|
public final class Signature extends Attribute {
|
||||||
|
|
||||||
|
private int signatureIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends ByteArrayInputStream to make 'unreading' chars possible.
|
* Construct object from file 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.
|
||||||
*/
|
*/
|
||||||
private static final class MyByteArrayInputStream extends ByteArrayInputStream {
|
Signature(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
||||||
|
this(nameIndex, length, input.readUnsignedShort(), constantPool);
|
||||||
|
}
|
||||||
|
|
||||||
MyByteArrayInputStream(final String data) {
|
/**
|
||||||
super(data.getBytes(StandardCharsets.UTF_8));
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
}
|
* @param length Content length in bytes
|
||||||
|
* @param signatureIndex Index in constant pool to CONSTANT_Utf8
|
||||||
|
* @param constantPool Array of constants
|
||||||
|
*/
|
||||||
|
public Signature(final int nameIndex, final int length, final int signatureIndex, final ConstantPool constantPool) {
|
||||||
|
super(Const.ATTR_SIGNATURE, nameIndex, Args.require(length, 2, "Signature length attribute"), constantPool);
|
||||||
|
this.signatureIndex = signatureIndex;
|
||||||
|
// validate:
|
||||||
|
Objects.requireNonNull(constantPool.getConstantUtf8(signatureIndex), "constantPool.getConstantUtf8(signatureIndex)");
|
||||||
|
}
|
||||||
|
|
||||||
String getData() {
|
/**
|
||||||
return new String(buf, StandardCharsets.UTF_8);
|
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
||||||
}
|
* physical copy.
|
||||||
|
*
|
||||||
void unread() {
|
* @param c Source to copy.
|
||||||
if (pos > 0) {
|
*/
|
||||||
pos--;
|
public Signature(final Signature c) {
|
||||||
}
|
this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean identStart(final int ch) {
|
private static boolean identStart(final int ch) {
|
||||||
@@ -152,44 +170,6 @@ public final class Signature extends Attribute {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int signatureIndex;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct object from file 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.
|
|
||||||
*/
|
|
||||||
Signature(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) throws IOException {
|
|
||||||
this(nameIndex, length, input.readUnsignedShort(), constantPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
|
||||||
* @param length Content length in bytes
|
|
||||||
* @param signatureIndex Index in constant pool to CONSTANT_Utf8
|
|
||||||
* @param constantPool Array of constants
|
|
||||||
*/
|
|
||||||
public Signature(final int nameIndex, final int length, final int signatureIndex, final ConstantPool constantPool) {
|
|
||||||
super(Const.ATTR_SIGNATURE, nameIndex, Args.require(length, 2, "Signature length attribute"), constantPool);
|
|
||||||
this.signatureIndex = signatureIndex;
|
|
||||||
// validate:
|
|
||||||
Objects.requireNonNull(constantPool.getConstantUtf8(signatureIndex), "constantPool.getConstantUtf8(signatureIndex)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize from another object. Note that both objects use the same references (shallow copy). Use clone() for a
|
|
||||||
* physical copy.
|
|
||||||
*
|
|
||||||
* @param c Source to copy.
|
|
||||||
*/
|
|
||||||
public Signature(final Signature c) {
|
|
||||||
this(c.getNameIndex(), c.getLength(), c.getSignatureIndex(), c.getConstantPool());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
|
* 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.
|
* I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
|
||||||
@@ -250,4 +230,24 @@ public final class Signature extends Attribute {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "Signature: " + getSignature();
|
return "Signature: " + getSignature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends ByteArrayInputStream to make 'unreading' chars possible.
|
||||||
|
*/
|
||||||
|
private static final class MyByteArrayInputStream extends ByteArrayInputStream {
|
||||||
|
|
||||||
|
MyByteArrayInputStream(final String data) {
|
||||||
|
super(data.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
String getData() {
|
||||||
|
return new String(buf, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unread() {
|
||||||
|
if (pos > 0) {
|
||||||
|
pos--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,19 +37,19 @@ public class SimpleElementValue extends ElementValue {
|
|||||||
final int type = super.getType();
|
final int type = super.getType();
|
||||||
dos.writeByte(type); // u1 kind of value
|
dos.writeByte(type); // u1 kind of value
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PRIMITIVE_INT:
|
case PRIMITIVE_INT:
|
||||||
case PRIMITIVE_BYTE:
|
case PRIMITIVE_BYTE:
|
||||||
case PRIMITIVE_CHAR:
|
case PRIMITIVE_CHAR:
|
||||||
case PRIMITIVE_FLOAT:
|
case PRIMITIVE_FLOAT:
|
||||||
case PRIMITIVE_LONG:
|
case PRIMITIVE_LONG:
|
||||||
case PRIMITIVE_BOOLEAN:
|
case PRIMITIVE_BOOLEAN:
|
||||||
case PRIMITIVE_SHORT:
|
case PRIMITIVE_SHORT:
|
||||||
case PRIMITIVE_DOUBLE:
|
case PRIMITIVE_DOUBLE:
|
||||||
case STRING:
|
case STRING:
|
||||||
dos.writeShort(getIndex());
|
dos.writeShort(getIndex());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type);
|
throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,10 @@ public class SimpleElementValue extends ElementValue {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIndex(final int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getValueBoolean() {
|
public boolean getValueBoolean() {
|
||||||
if (super.getType() != PRIMITIVE_BOOLEAN) {
|
if (super.getType() != PRIMITIVE_BOOLEAN) {
|
||||||
throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue");
|
throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue");
|
||||||
@@ -128,46 +132,42 @@ public class SimpleElementValue extends ElementValue {
|
|||||||
return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
|
return super.getConstantPool().getConstantUtf8(getIndex()).getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndex(final int index) {
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whatever kind of value it is, return it as a string
|
// Whatever kind of value it is, return it as a string
|
||||||
@Override
|
@Override
|
||||||
public String stringifyValue() {
|
public String stringifyValue() {
|
||||||
final ConstantPool cpool = super.getConstantPool();
|
final ConstantPool cpool = super.getConstantPool();
|
||||||
final int type = super.getType();
|
final int type = super.getType();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PRIMITIVE_INT:
|
case PRIMITIVE_INT:
|
||||||
return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
|
return Integer.toString(cpool.getConstantInteger(getIndex()).getBytes());
|
||||||
case PRIMITIVE_LONG:
|
case PRIMITIVE_LONG:
|
||||||
final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
|
final ConstantLong j = cpool.getConstant(getIndex(), Const.CONSTANT_Long, ConstantLong.class);
|
||||||
return Long.toString(j.getBytes());
|
return Long.toString(j.getBytes());
|
||||||
case PRIMITIVE_DOUBLE:
|
case PRIMITIVE_DOUBLE:
|
||||||
final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
|
final ConstantDouble d = cpool.getConstant(getIndex(), Const.CONSTANT_Double, ConstantDouble.class);
|
||||||
return Double.toString(d.getBytes());
|
return Double.toString(d.getBytes());
|
||||||
case PRIMITIVE_FLOAT:
|
case PRIMITIVE_FLOAT:
|
||||||
final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
|
final ConstantFloat f = cpool.getConstant(getIndex(), Const.CONSTANT_Float, ConstantFloat.class);
|
||||||
return Float.toString(f.getBytes());
|
return Float.toString(f.getBytes());
|
||||||
case PRIMITIVE_SHORT:
|
case PRIMITIVE_SHORT:
|
||||||
final ConstantInteger s = cpool.getConstantInteger(getIndex());
|
final ConstantInteger s = cpool.getConstantInteger(getIndex());
|
||||||
return Integer.toString(s.getBytes());
|
return Integer.toString(s.getBytes());
|
||||||
case PRIMITIVE_BYTE:
|
case PRIMITIVE_BYTE:
|
||||||
final ConstantInteger b = cpool.getConstantInteger(getIndex());
|
final ConstantInteger b = cpool.getConstantInteger(getIndex());
|
||||||
return Integer.toString(b.getBytes());
|
return Integer.toString(b.getBytes());
|
||||||
case PRIMITIVE_CHAR:
|
case PRIMITIVE_CHAR:
|
||||||
final ConstantInteger ch = cpool.getConstantInteger(getIndex());
|
final ConstantInteger ch = cpool.getConstantInteger(getIndex());
|
||||||
return String.valueOf((char) ch.getBytes());
|
return String.valueOf((char) ch.getBytes());
|
||||||
case PRIMITIVE_BOOLEAN:
|
case PRIMITIVE_BOOLEAN:
|
||||||
final ConstantInteger bo = cpool.getConstantInteger(getIndex());
|
final ConstantInteger bo = cpool.getConstantInteger(getIndex());
|
||||||
if (bo.getBytes() == 0) {
|
if (bo.getBytes() == 0) {
|
||||||
return "false";
|
return "false";
|
||||||
}
|
}
|
||||||
return "true";
|
return "true";
|
||||||
case STRING:
|
case STRING:
|
||||||
return cpool.getConstantUtf8(getIndex()).getBytes();
|
return cpool.getConstantUtf8(getIndex()).getBytes();
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
|
throw new IllegalStateException("SimpleElementValue class does not know how to stringify type " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ public final class SourceFile extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -48,13 +48,13 @@ public final class SourceFile extends Attribute {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "SourceFile".
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "SourceFile".
|
||||||
* @param length Content length in bytes, the value should be 2.
|
* @param length Content length in bytes, the value should be 2.
|
||||||
* @param constantPool The constant pool that this attribute is associated with.
|
* @param constantPool The constant pool that this attribute is associated with.
|
||||||
* @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This string will be interpreted as the name of the
|
* @param sourceFileIndex Index in constant pool to CONSTANT_Utf8. This string will be interpreted as the name of the
|
||||||
* file from which this class was compiled. It will not be interpreted as indicating the name of the directory
|
* file from which this class was compiled. It will not be interpreted as indicating the name of the directory
|
||||||
* contqining the file or an absolute path; this information has to be supplied the consumer of this attribute -
|
* contqining the file or an absolute path; this information has to be supplied the consumer of this attribute -
|
||||||
* in many cases, the JVM.
|
* in many cases, the JVM.
|
||||||
*/
|
*/
|
||||||
public SourceFile(final int nameIndex, final int length, final int sourceFileIndex, final ConstantPool constantPool) {
|
public SourceFile(final int nameIndex, final int length, final int sourceFileIndex, final ConstantPool constantPool) {
|
||||||
super(Const.ATTR_SOURCE_FILE, nameIndex, Args.require(length, 2, "SourceFile length attribute"), constantPool);
|
super(Const.ATTR_SOURCE_FILE, nameIndex, Args.require(length, 2, "SourceFile length attribute"), constantPool);
|
||||||
@@ -109,13 +109,6 @@ public final class SourceFile extends Attribute {
|
|||||||
return sourceFileIndex;
|
return sourceFileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Source file name.
|
|
||||||
*/
|
|
||||||
public String getSourceFileName() {
|
|
||||||
return super.getConstantPool().getConstantUtf8(sourceFileIndex).getBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param sourceFileIndex
|
* @param sourceFileIndex
|
||||||
*/
|
*/
|
||||||
@@ -123,6 +116,13 @@ public final class SourceFile extends Attribute {
|
|||||||
this.sourceFileIndex = sourceFileIndex;
|
this.sourceFileIndex = sourceFileIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Source file name.
|
||||||
|
*/
|
||||||
|
public String getSourceFileName() {
|
||||||
|
return super.getConstantPool().getConstantUtf8(sourceFileIndex).getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation
|
* @return String representation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ public final class StackMap extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index of name
|
* @param nameIndex Index of name
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param dataInput Input stream
|
* @param dataInput Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.util.Arrays;
|
|||||||
/**
|
/**
|
||||||
* This class represents a stack map entry recording the types of local variables and the of stack items at a given
|
* This class represents a stack map entry recording the types of local variables and the of stack items at a given
|
||||||
* byte code offset. See CLDC specification 5.3.1.2.
|
* byte code offset. See CLDC specification 5.3.1.2.
|
||||||
*
|
* <p>
|
||||||
* See also https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4
|
* See also https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.4
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
@@ -41,6 +41,7 @@ import java.util.Arrays;
|
|||||||
* full_frame;
|
* full_frame;
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
|
*
|
||||||
* @see StackMap
|
* @see StackMap
|
||||||
* @see StackMapType
|
* @see StackMapType
|
||||||
*/
|
*/
|
||||||
@@ -67,10 +68,10 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
byteCodeOffset = frameType - Const.SAME_FRAME;
|
byteCodeOffset = frameType - Const.SAME_FRAME;
|
||||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||||
byteCodeOffset = frameType - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
byteCodeOffset = frameType - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||||
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
|
typesOfStackItems = new StackMapType[]{new StackMapType(dataInput, constantPool)};
|
||||||
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
} else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
|
||||||
byteCodeOffset = dataInput.readUnsignedShort();
|
byteCodeOffset = dataInput.readUnsignedShort();
|
||||||
typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
|
typesOfStackItems = new StackMapType[]{new StackMapType(dataInput, constantPool)};
|
||||||
} else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
|
} else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
|
||||||
byteCodeOffset = dataInput.readUnsignedShort();
|
byteCodeOffset = dataInput.readUnsignedShort();
|
||||||
} else if (frameType == Const.SAME_FRAME_EXTENDED) {
|
} else if (frameType == Const.SAME_FRAME_EXTENDED) {
|
||||||
@@ -104,16 +105,16 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
* DO NOT USE
|
* DO NOT USE
|
||||||
*
|
*
|
||||||
* @param byteCodeOffset
|
* @param byteCodeOffset
|
||||||
* @param numberOfLocals NOT USED
|
* @param numberOfLocals NOT USED
|
||||||
* @param typesOfLocals array of {@link StackMapType}s of locals
|
* @param typesOfLocals array of {@link StackMapType}s of locals
|
||||||
* @param numberOfStackItems NOT USED
|
* @param numberOfStackItems NOT USED
|
||||||
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
||||||
* @param constantPool the constant pool
|
* @param constantPool the constant pool
|
||||||
* @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)} instead
|
* @deprecated Since 6.0, use {@link #StackMapEntry(int, int, StackMapType[], StackMapType[], ConstantPool)} instead
|
||||||
*/
|
*/
|
||||||
@java.lang.Deprecated
|
@java.lang.Deprecated
|
||||||
public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, final StackMapType[] typesOfLocals, final int numberOfStackItems,
|
public StackMapEntry(final int byteCodeOffset, final int numberOfLocals, final StackMapType[] typesOfLocals, final int numberOfStackItems,
|
||||||
final StackMapType[] typesOfStackItems, final ConstantPool constantPool) {
|
final StackMapType[] typesOfStackItems, final ConstantPool constantPool) {
|
||||||
this.byteCodeOffset = byteCodeOffset;
|
this.byteCodeOffset = byteCodeOffset;
|
||||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
||||||
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY;
|
this.typesOfStackItems = typesOfStackItems != null ? typesOfStackItems : StackMapType.EMPTY_ARRAY;
|
||||||
@@ -129,14 +130,14 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
/**
|
/**
|
||||||
* Create an instance
|
* Create an instance
|
||||||
*
|
*
|
||||||
* @param tag the frameType to use
|
* @param tag the frameType to use
|
||||||
* @param byteCodeOffset
|
* @param byteCodeOffset
|
||||||
* @param typesOfLocals array of {@link StackMapType}s of locals
|
* @param typesOfLocals array of {@link StackMapType}s of locals
|
||||||
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
* @param typesOfStackItems array ot {@link StackMapType}s of stack items
|
||||||
* @param constantPool the constant pool
|
* @param constantPool the constant pool
|
||||||
*/
|
*/
|
||||||
public StackMapEntry(final int tag, final int byteCodeOffset, final StackMapType[] typesOfLocals, final StackMapType[] typesOfStackItems,
|
public StackMapEntry(final int tag, final int byteCodeOffset, final StackMapType[] typesOfLocals, final StackMapType[] typesOfStackItems,
|
||||||
final ConstantPool constantPool) {
|
final ConstantPool constantPool) {
|
||||||
this.frameType = tag;
|
this.frameType = tag;
|
||||||
this.byteCodeOffset = byteCodeOffset;
|
this.byteCodeOffset = byteCodeOffset;
|
||||||
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
this.typesOfLocals = typesOfLocals != null ? typesOfLocals : StackMapType.EMPTY_ARRAY;
|
||||||
@@ -215,6 +216,29 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
return byteCodeOffset;
|
return byteCodeOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setByteCodeOffset(final int newOffset) {
|
||||||
|
if (newOffset < 0 || newOffset > 32767) {
|
||||||
|
throw new IllegalArgumentException("Invalid StackMap offset: " + newOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||||
|
if (newOffset > Const.SAME_FRAME_MAX) {
|
||||||
|
frameType = Const.SAME_FRAME_EXTENDED;
|
||||||
|
} else {
|
||||||
|
frameType = newOffset;
|
||||||
|
}
|
||||||
|
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||||
|
if (newOffset > Const.SAME_FRAME_MAX) {
|
||||||
|
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
|
||||||
|
} else {
|
||||||
|
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + newOffset;
|
||||||
|
}
|
||||||
|
} else if (invalidFrameType(frameType)) {
|
||||||
|
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
||||||
|
}
|
||||||
|
byteCodeOffset = newOffset;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Constant pool used by this object.
|
* @return Constant pool used by this object.
|
||||||
*/
|
*/
|
||||||
@@ -222,13 +246,30 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
return constantPool;
|
return constantPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param constantPool Constant pool to be used for this object.
|
||||||
|
*/
|
||||||
|
public void setConstantPool(final ConstantPool constantPool) {
|
||||||
|
this.constantPool = constantPool;
|
||||||
|
}
|
||||||
|
|
||||||
public int getFrameType() {
|
public int getFrameType() {
|
||||||
return frameType;
|
return frameType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFrameType(final int ft) {
|
||||||
|
if (ft >= Const.SAME_FRAME && ft <= Const.SAME_FRAME_MAX) {
|
||||||
|
byteCodeOffset = ft - Const.SAME_FRAME;
|
||||||
|
} else if (ft >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && ft <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
||||||
|
byteCodeOffset = ft - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
||||||
|
} else if (invalidFrameType(ft)) {
|
||||||
|
throw new IllegalArgumentException("Invalid StackMap frameType");
|
||||||
|
}
|
||||||
|
frameType = ft;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate stack map entry size
|
* Calculate stack map entry size
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int getMapEntrySize() {
|
int getMapEntrySize() {
|
||||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
||||||
@@ -267,18 +308,40 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
return typesOfLocals.length;
|
return typesOfLocals.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 6.0
|
||||||
|
*/
|
||||||
|
@java.lang.Deprecated
|
||||||
|
public void setNumberOfLocals(final int n) { // TODO unused
|
||||||
|
}
|
||||||
|
|
||||||
public int getNumberOfStackItems() {
|
public int getNumberOfStackItems() {
|
||||||
return typesOfStackItems.length;
|
return typesOfStackItems.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 6.0
|
||||||
|
*/
|
||||||
|
@java.lang.Deprecated
|
||||||
|
public void setNumberOfStackItems(final int n) { // TODO unused
|
||||||
|
}
|
||||||
|
|
||||||
public StackMapType[] getTypesOfLocals() {
|
public StackMapType[] getTypesOfLocals() {
|
||||||
return typesOfLocals;
|
return typesOfLocals;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTypesOfLocals(final StackMapType[] types) {
|
||||||
|
typesOfLocals = types != null ? types : StackMapType.EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
public StackMapType[] getTypesOfStackItems() {
|
public StackMapType[] getTypesOfStackItems() {
|
||||||
return typesOfStackItems;
|
return typesOfStackItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTypesOfStackItems(final StackMapType[] types) {
|
||||||
|
typesOfStackItems = types != null ? types : StackMapType.EMPTY_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean invalidFrameType(final int f) {
|
private boolean invalidFrameType(final int f) {
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
return f != Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
|
return f != Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED
|
||||||
@@ -289,71 +352,6 @@ public final class StackMapEntry implements Node, Cloneable {
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setByteCodeOffset(final int newOffset) {
|
|
||||||
if (newOffset < 0 || newOffset > 32767) {
|
|
||||||
throw new IllegalArgumentException("Invalid StackMap offset: " + newOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
|
|
||||||
if (newOffset > Const.SAME_FRAME_MAX) {
|
|
||||||
frameType = Const.SAME_FRAME_EXTENDED;
|
|
||||||
} else {
|
|
||||||
frameType = newOffset;
|
|
||||||
}
|
|
||||||
} else if (frameType >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && frameType <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
|
||||||
if (newOffset > Const.SAME_FRAME_MAX) {
|
|
||||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
|
|
||||||
} else {
|
|
||||||
frameType = Const.SAME_LOCALS_1_STACK_ITEM_FRAME + newOffset;
|
|
||||||
}
|
|
||||||
} else if (invalidFrameType(frameType)) {
|
|
||||||
throw new IllegalStateException("Invalid StackMap frameType: " + frameType);
|
|
||||||
}
|
|
||||||
byteCodeOffset = newOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param constantPool Constant pool to be used for this object.
|
|
||||||
*/
|
|
||||||
public void setConstantPool(final ConstantPool constantPool) {
|
|
||||||
this.constantPool = constantPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFrameType(final int ft) {
|
|
||||||
if (ft >= Const.SAME_FRAME && ft <= Const.SAME_FRAME_MAX) {
|
|
||||||
byteCodeOffset = ft - Const.SAME_FRAME;
|
|
||||||
} else if (ft >= Const.SAME_LOCALS_1_STACK_ITEM_FRAME && ft <= Const.SAME_LOCALS_1_STACK_ITEM_FRAME_MAX) {
|
|
||||||
byteCodeOffset = ft - Const.SAME_LOCALS_1_STACK_ITEM_FRAME;
|
|
||||||
} else if (invalidFrameType(ft)) {
|
|
||||||
throw new IllegalArgumentException("Invalid StackMap frameType");
|
|
||||||
}
|
|
||||||
frameType = ft;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated since 6.0
|
|
||||||
*/
|
|
||||||
@java.lang.Deprecated
|
|
||||||
public void setNumberOfLocals(final int n) { // TODO unused
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated since 6.0
|
|
||||||
*/
|
|
||||||
@java.lang.Deprecated
|
|
||||||
public void setNumberOfStackItems(final int n) { // TODO unused
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypesOfLocals(final StackMapType[] types) {
|
|
||||||
typesOfLocals = types != null ? types : StackMapType.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypesOfStackItems(final StackMapType[] types) {
|
|
||||||
typesOfStackItems = types != null ? types : StackMapType.EMPTY_ARRAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public final class StackMapType implements Cloneable {
|
|||||||
private ConstantPool constantPool;
|
private ConstantPool constantPool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param type type tag as defined in the Constants interface
|
* @param type type tag as defined in the Constants interface
|
||||||
* @param index index to constant pool, or byte code offset
|
* @param index index to constant pool, or byte code offset
|
||||||
*/
|
*/
|
||||||
public StackMapType(final byte type, final int index, final ConstantPool constantPool) {
|
public StackMapType(final byte type, final int index, final ConstantPool constantPool) {
|
||||||
@@ -100,18 +100,33 @@ public final class StackMapType implements Cloneable {
|
|||||||
return constantPool;
|
return constantPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param constantPool Constant pool to be used for this object.
|
||||||
|
*/
|
||||||
|
public void setConstantPool(final ConstantPool constantPool) {
|
||||||
|
this.constantPool = constantPool;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1
|
* @return index to constant pool if type == ITEM_Object, or offset in byte code, if type == ITEM_NewObject, and -1
|
||||||
* otherwise
|
* otherwise
|
||||||
*/
|
*/
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIndex(final int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
public byte getType() {
|
public byte getType() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setType(final byte type) {
|
||||||
|
this.type = checkType(type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true, if type is either ITEM_Object or ITEM_NewObject
|
* @return true, if type is either ITEM_Object or ITEM_NewObject
|
||||||
*/
|
*/
|
||||||
@@ -132,21 +147,6 @@ public final class StackMapType implements Cloneable {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param constantPool Constant pool to be used for this object.
|
|
||||||
*/
|
|
||||||
public void setConstantPool(final ConstantPool constantPool) {
|
|
||||||
this.constantPool = constantPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIndex(final int index) {
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setType(final byte type) {
|
|
||||||
this.type = checkType(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation
|
* @return String representation
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ public final class Synthetic extends Attribute {
|
|||||||
private byte[] bytes;
|
private byte[] bytes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "Synthetic".
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8, which should represent the string "Synthetic".
|
||||||
* @param length Content length in bytes - should be zero.
|
* @param length Content length in bytes - should be zero.
|
||||||
* @param bytes Attribute contents
|
* @param bytes Attribute contents
|
||||||
* @param constantPool The constant pool this attribute is associated with.
|
* @param constantPool The constant pool this attribute is associated with.
|
||||||
*/
|
*/
|
||||||
public Synthetic(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
public Synthetic(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||||
@@ -49,9 +49,9 @@ public final class Synthetic extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Construct object from input stream.
|
* Construct object from input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
* @param nameIndex Index in constant pool to CONSTANT_Utf8
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -34,16 +34,15 @@ import java.util.Arrays;
|
|||||||
*/
|
*/
|
||||||
public final class Unknown extends Attribute {
|
public final class Unknown extends Attribute {
|
||||||
|
|
||||||
private byte[] bytes;
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private byte[] bytes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new instance for a non-standard attribute.
|
* Constructs a new instance for a non-standard attribute.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param bytes Attribute contents
|
* @param bytes Attribute contents
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
*/
|
*/
|
||||||
public Unknown(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
public Unknown(final int nameIndex, final int length, final byte[] bytes, final ConstantPool constantPool) {
|
||||||
@@ -55,9 +54,9 @@ public final class Unknown extends Attribute {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new instance from an input stream.
|
* Constructs a new instance from an input stream.
|
||||||
*
|
*
|
||||||
* @param nameIndex Index in constant pool
|
* @param nameIndex Index in constant pool
|
||||||
* @param length Content length in bytes
|
* @param length Content length in bytes
|
||||||
* @param input Input stream
|
* @param input Input stream
|
||||||
* @param constantPool Array of constants
|
* @param constantPool Array of constants
|
||||||
* @throws IOException if an I/O error occurs.
|
* @throws IOException if an I/O error occurs.
|
||||||
*/
|
*/
|
||||||
@@ -123,6 +122,13 @@ public final class Unknown extends Attribute {
|
|||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bytes the bytes to set
|
||||||
|
*/
|
||||||
|
public void setBytes(final byte[] bytes) {
|
||||||
|
this.bytes = bytes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return name of attribute.
|
* @return name of attribute.
|
||||||
*/
|
*/
|
||||||
@@ -131,13 +137,6 @@ public final class Unknown extends Attribute {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param bytes the bytes to set
|
|
||||||
*/
|
|
||||||
public void setBytes(final byte[] bytes) {
|
|
||||||
this.bytes = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return String representation.
|
* @return String representation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -31,15 +31,13 @@ public interface UnknownAttributeReader {
|
|||||||
* associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the
|
* associated with it. As the class file parser parses attributes, it will call various AttributeReaders based on the
|
||||||
* name of the attributes it is constructing.
|
* name of the attributes it is constructing.
|
||||||
*
|
*
|
||||||
* @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute.
|
* @param nameIndex An index into the constant pool, indexing a ConstantUtf8 that represents the name of the attribute.
|
||||||
* @param length The length of the data contained in the attribute. This is written into the constant pool and should
|
* @param length The length of the data contained in the attribute. This is written into the constant pool and should
|
||||||
* agree with what the factory expects the length to be.
|
* agree with what the factory expects the length to be.
|
||||||
* @param file This is the data input that the factory needs to read its data from.
|
* @param file This is the data input that the factory needs to read its data from.
|
||||||
* @param constantPool This is the constant pool associated with the Attribute that we are constructing.
|
* @param constantPool This is the constant pool associated with the Attribute that we are constructing.
|
||||||
*
|
|
||||||
* @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of
|
* @return The user-defined AttributeReader should take this data and use it to construct an attribute. In the case of
|
||||||
* errors, a null can be returned which will cause the parsing of the class file to fail.
|
* errors, a null can be returned which will cause the parsing of the class file to fail.
|
||||||
*
|
|
||||||
* @see Attribute#addAttributeReader(String, UnknownAttributeReader)
|
* @see Attribute#addAttributeReader(String, UnknownAttributeReader)
|
||||||
*/
|
*/
|
||||||
Attribute createAttribute(int nameIndex, int length, java.io.DataInput file, ConstantPool constantPool);
|
Attribute createAttribute(int nameIndex, int length, java.io.DataInput file, ConstantPool constantPool);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -53,6 +53,6 @@ public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackP
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Class<?>[] getExceptions() {
|
public Class<?>[] getExceptions() {
|
||||||
return new Class[] {ExceptionConst.NULL_POINTER_EXCEPTION};
|
return new Class[]{ExceptionConst.NULL_POINTER_EXCEPTION};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,6 @@ public class ATHROW extends Instruction implements UnconditionalBranch, Exceptio
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Class<?>[] getExceptions() {
|
public Class<?>[] getExceptions() {
|
||||||
return new Class[] {ExceptionConst.THROWABLE};
|
return new Class[]{ExceptionConst.THROWABLE};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,43 @@ import java.util.List;
|
|||||||
public class AnnotationEntryGen {
|
public class AnnotationEntryGen {
|
||||||
|
|
||||||
static final AnnotationEntryGen[] EMPTY_ARRAY = {};
|
static final AnnotationEntryGen[] EMPTY_ARRAY = {};
|
||||||
|
private final ConstantPoolGen cpool;
|
||||||
|
private int typeIndex;
|
||||||
|
private List<ElementValuePairGen> evs;
|
||||||
|
private boolean isRuntimeVisible;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Here we are taking a fixed annotation of type Annotation and building a modifiable AnnotationGen object. If the pool
|
||||||
|
* passed in is for a different class file, then copyPoolEntries should have been passed as true as that will force us
|
||||||
|
* to do a deep copy of the annotation and move the cpool entries across. We need to copy the type and the element name
|
||||||
|
* value pairs and the visibility.
|
||||||
|
*/
|
||||||
|
public AnnotationEntryGen(final AnnotationEntry a, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
||||||
|
this.cpool = cpool;
|
||||||
|
if (copyPoolEntries) {
|
||||||
|
typeIndex = cpool.addUtf8(a.getAnnotationType());
|
||||||
|
} else {
|
||||||
|
typeIndex = a.getAnnotationTypeIndex();
|
||||||
|
}
|
||||||
|
isRuntimeVisible = a.isRuntimeVisible();
|
||||||
|
evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnnotationEntryGen(final ConstantPoolGen cpool) {
|
||||||
|
this.cpool = cpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnnotationEntryGen(final ObjectType type, final List<ElementValuePairGen> elements, final boolean vis, final ConstantPoolGen cpool) {
|
||||||
|
this.cpool = cpool;
|
||||||
|
this.typeIndex = cpool.addUtf8(type.getSignature());
|
||||||
|
evs = elements;
|
||||||
|
isRuntimeVisible = vis;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a list of AnnotationGen objects into a set of attributes that can be attached to the class file.
|
* Converts a list of AnnotationGen objects into a set of attributes that can be attached to the class file.
|
||||||
*
|
*
|
||||||
* @param cp The constant pool gen where we can create the necessary name refs
|
* @param cp The constant pool gen where we can create the necessary name refs
|
||||||
* @param annotationEntryGens An array of AnnotationGen objects
|
* @param annotationEntryGens An array of AnnotationGen objects
|
||||||
*/
|
*/
|
||||||
static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) {
|
static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) {
|
||||||
@@ -86,11 +118,11 @@ public class AnnotationEntryGen {
|
|||||||
final List<Attribute> newAttributes = new ArrayList<>();
|
final List<Attribute> newAttributes = new ArrayList<>();
|
||||||
if (rvaData.length > 2) {
|
if (rvaData.length > 2) {
|
||||||
newAttributes
|
newAttributes
|
||||||
.add(new RuntimeVisibleAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool()));
|
.add(new RuntimeVisibleAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)), cp.getConstantPool()));
|
||||||
}
|
}
|
||||||
if (riaData.length > 2) {
|
if (riaData.length > 2) {
|
||||||
newAttributes.add(
|
newAttributes.add(
|
||||||
new RuntimeInvisibleAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool()));
|
new RuntimeInvisibleAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)), cp.getConstantPool()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return newAttributes.toArray(Attribute.EMPTY_ARRAY);
|
return newAttributes.toArray(Attribute.EMPTY_ARRAY);
|
||||||
@@ -106,7 +138,7 @@ public class AnnotationEntryGen {
|
|||||||
* RuntimeInvisibleParameterAnnotations
|
* RuntimeInvisibleParameterAnnotations
|
||||||
*/
|
*/
|
||||||
static Attribute[] getParameterAnnotationAttributes(final ConstantPoolGen cp,
|
static Attribute[] getParameterAnnotationAttributes(final ConstantPoolGen cp,
|
||||||
final List<AnnotationEntryGen>[] /* Array of lists, array size depends on #params */ vec) {
|
final List<AnnotationEntryGen>[] /* Array of lists, array size depends on #params */ vec) {
|
||||||
final int[] visCount = new int[vec.length];
|
final int[] visCount = new int[vec.length];
|
||||||
int totalVisCount = 0;
|
int totalVisCount = 0;
|
||||||
final int[] invisCount = new int[vec.length];
|
final int[] invisCount = new int[vec.length];
|
||||||
@@ -168,11 +200,11 @@ public class AnnotationEntryGen {
|
|||||||
final List<Attribute> newAttributes = new ArrayList<>();
|
final List<Attribute> newAttributes = new ArrayList<>();
|
||||||
if (totalVisCount > 0) {
|
if (totalVisCount > 0) {
|
||||||
newAttributes.add(new RuntimeVisibleParameterAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)),
|
newAttributes.add(new RuntimeVisibleParameterAnnotations(rvaIndex, rvaData.length, new DataInputStream(new ByteArrayInputStream(rvaData)),
|
||||||
cp.getConstantPool()));
|
cp.getConstantPool()));
|
||||||
}
|
}
|
||||||
if (totalInvisCount > 0) {
|
if (totalInvisCount > 0) {
|
||||||
newAttributes.add(new RuntimeInvisibleParameterAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)),
|
newAttributes.add(new RuntimeInvisibleParameterAnnotations(riaIndex, riaData.length, new DataInputStream(new ByteArrayInputStream(riaData)),
|
||||||
cp.getConstantPool()));
|
cp.getConstantPool()));
|
||||||
}
|
}
|
||||||
return newAttributes.toArray(Attribute.EMPTY_ARRAY);
|
return newAttributes.toArray(Attribute.EMPTY_ARRAY);
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
@@ -194,42 +226,6 @@ public class AnnotationEntryGen {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int typeIndex;
|
|
||||||
|
|
||||||
private List<ElementValuePairGen> evs;
|
|
||||||
|
|
||||||
private final ConstantPoolGen cpool;
|
|
||||||
|
|
||||||
private boolean isRuntimeVisible;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Here we are taking a fixed annotation of type Annotation and building a modifiable AnnotationGen object. If the pool
|
|
||||||
* passed in is for a different class file, then copyPoolEntries should have been passed as true as that will force us
|
|
||||||
* to do a deep copy of the annotation and move the cpool entries across. We need to copy the type and the element name
|
|
||||||
* value pairs and the visibility.
|
|
||||||
*/
|
|
||||||
public AnnotationEntryGen(final AnnotationEntry a, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
|
||||||
this.cpool = cpool;
|
|
||||||
if (copyPoolEntries) {
|
|
||||||
typeIndex = cpool.addUtf8(a.getAnnotationType());
|
|
||||||
} else {
|
|
||||||
typeIndex = a.getAnnotationTypeIndex();
|
|
||||||
}
|
|
||||||
isRuntimeVisible = a.isRuntimeVisible();
|
|
||||||
evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private AnnotationEntryGen(final ConstantPoolGen cpool) {
|
|
||||||
this.cpool = cpool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnnotationEntryGen(final ObjectType type, final List<ElementValuePairGen> elements, final boolean vis, final ConstantPoolGen cpool) {
|
|
||||||
this.cpool = cpool;
|
|
||||||
this.typeIndex = cpool.addUtf8(type.getSignature());
|
|
||||||
evs = elements;
|
|
||||||
isRuntimeVisible = vis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addElementNameValuePair(final ElementValuePairGen evp) {
|
public void addElementNameValuePair(final ElementValuePairGen evp) {
|
||||||
if (evs == null) {
|
if (evs == null) {
|
||||||
evs = new ArrayList<>();
|
evs = new ArrayList<>();
|
||||||
|
|||||||
@@ -43,48 +43,48 @@ public abstract class ArithmeticInstruction extends Instruction implements Typed
|
|||||||
public Type getType(final ConstantPoolGen cp) {
|
public Type getType(final ConstantPoolGen cp) {
|
||||||
final short opcode = super.getOpcode();
|
final short opcode = super.getOpcode();
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Const.DADD:
|
case Const.DADD:
|
||||||
case Const.DDIV:
|
case Const.DDIV:
|
||||||
case Const.DMUL:
|
case Const.DMUL:
|
||||||
case Const.DNEG:
|
case Const.DNEG:
|
||||||
case Const.DREM:
|
case Const.DREM:
|
||||||
case Const.DSUB:
|
case Const.DSUB:
|
||||||
return Type.DOUBLE;
|
return Type.DOUBLE;
|
||||||
case Const.FADD:
|
case Const.FADD:
|
||||||
case Const.FDIV:
|
case Const.FDIV:
|
||||||
case Const.FMUL:
|
case Const.FMUL:
|
||||||
case Const.FNEG:
|
case Const.FNEG:
|
||||||
case Const.FREM:
|
case Const.FREM:
|
||||||
case Const.FSUB:
|
case Const.FSUB:
|
||||||
return Type.FLOAT;
|
return Type.FLOAT;
|
||||||
case Const.IADD:
|
case Const.IADD:
|
||||||
case Const.IAND:
|
case Const.IAND:
|
||||||
case Const.IDIV:
|
case Const.IDIV:
|
||||||
case Const.IMUL:
|
case Const.IMUL:
|
||||||
case Const.INEG:
|
case Const.INEG:
|
||||||
case Const.IOR:
|
case Const.IOR:
|
||||||
case Const.IREM:
|
case Const.IREM:
|
||||||
case Const.ISHL:
|
case Const.ISHL:
|
||||||
case Const.ISHR:
|
case Const.ISHR:
|
||||||
case Const.ISUB:
|
case Const.ISUB:
|
||||||
case Const.IUSHR:
|
case Const.IUSHR:
|
||||||
case Const.IXOR:
|
case Const.IXOR:
|
||||||
return Type.INT;
|
return Type.INT;
|
||||||
case Const.LADD:
|
case Const.LADD:
|
||||||
case Const.LAND:
|
case Const.LAND:
|
||||||
case Const.LDIV:
|
case Const.LDIV:
|
||||||
case Const.LMUL:
|
case Const.LMUL:
|
||||||
case Const.LNEG:
|
case Const.LNEG:
|
||||||
case Const.LOR:
|
case Const.LOR:
|
||||||
case Const.LREM:
|
case Const.LREM:
|
||||||
case Const.LSHL:
|
case Const.LSHL:
|
||||||
case Const.LSHR:
|
case Const.LSHR:
|
||||||
case Const.LSUB:
|
case Const.LSUB:
|
||||||
case Const.LUSHR:
|
case Const.LUSHR:
|
||||||
case Const.LXOR:
|
case Const.LXOR:
|
||||||
return Type.LONG;
|
return Type.LONG;
|
||||||
default: // Never reached
|
default: // Never reached
|
||||||
throw new ClassGenException("Unknown type " + opcode);
|
throw new ClassGenException("Unknown type " + opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,32 +49,32 @@ public abstract class ArrayInstruction extends Instruction implements ExceptionT
|
|||||||
public Type getType(final ConstantPoolGen cp) {
|
public Type getType(final ConstantPoolGen cp) {
|
||||||
final short opcode = super.getOpcode();
|
final short opcode = super.getOpcode();
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Const.IALOAD:
|
case Const.IALOAD:
|
||||||
case Const.IASTORE:
|
case Const.IASTORE:
|
||||||
return Type.INT;
|
return Type.INT;
|
||||||
case Const.CALOAD:
|
case Const.CALOAD:
|
||||||
case Const.CASTORE:
|
case Const.CASTORE:
|
||||||
return Type.CHAR;
|
return Type.CHAR;
|
||||||
case Const.BALOAD:
|
case Const.BALOAD:
|
||||||
case Const.BASTORE:
|
case Const.BASTORE:
|
||||||
return Type.BYTE;
|
return Type.BYTE;
|
||||||
case Const.SALOAD:
|
case Const.SALOAD:
|
||||||
case Const.SASTORE:
|
case Const.SASTORE:
|
||||||
return Type.SHORT;
|
return Type.SHORT;
|
||||||
case Const.LALOAD:
|
case Const.LALOAD:
|
||||||
case Const.LASTORE:
|
case Const.LASTORE:
|
||||||
return Type.LONG;
|
return Type.LONG;
|
||||||
case Const.DALOAD:
|
case Const.DALOAD:
|
||||||
case Const.DASTORE:
|
case Const.DASTORE:
|
||||||
return Type.DOUBLE;
|
return Type.DOUBLE;
|
||||||
case Const.FALOAD:
|
case Const.FALOAD:
|
||||||
case Const.FASTORE:
|
case Const.FASTORE:
|
||||||
return Type.FLOAT;
|
return Type.FLOAT;
|
||||||
case Const.AALOAD:
|
case Const.AALOAD:
|
||||||
case Const.AASTORE:
|
case Const.AASTORE:
|
||||||
return Type.OBJECT;
|
return Type.OBJECT;
|
||||||
default:
|
default:
|
||||||
throw new ClassGenException("Unknown case in switch" + opcode);
|
throw new ClassGenException("Unknown case in switch" + opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public final class ArrayType extends ReferenceType {
|
|||||||
/**
|
/**
|
||||||
* Convenience constructor for array type, e.g. int[]
|
* Convenience constructor for array type, e.g. int[]
|
||||||
*
|
*
|
||||||
* @param type array type, e.g. T_INT
|
* @param type array type, e.g. T_INT
|
||||||
* @param dimensions array dimensions
|
* @param dimensions array dimensions
|
||||||
*/
|
*/
|
||||||
public ArrayType(final byte type, final int dimensions) {
|
public ArrayType(final byte type, final int dimensions) {
|
||||||
@@ -39,7 +39,7 @@ public final class ArrayType extends ReferenceType {
|
|||||||
/**
|
/**
|
||||||
* Convenience constructor for reference array type, e.g. Object[]
|
* Convenience constructor for reference array type, e.g. Object[]
|
||||||
*
|
*
|
||||||
* @param className complete name of class (java.lang.String, e.g.)
|
* @param className complete name of class (java.lang.String, e.g.)
|
||||||
* @param dimensions array dimensions
|
* @param dimensions array dimensions
|
||||||
*/
|
*/
|
||||||
public ArrayType(final String className, final int dimensions) {
|
public ArrayType(final String className, final int dimensions) {
|
||||||
@@ -49,7 +49,7 @@ public final class ArrayType extends ReferenceType {
|
|||||||
/**
|
/**
|
||||||
* Constructor for array of given type
|
* Constructor for array of given type
|
||||||
*
|
*
|
||||||
* @param type type of array (may be an array itself)
|
* @param type type of array (may be an array itself)
|
||||||
* @param dimensions array dimensions
|
* @param dimensions array dimensions
|
||||||
*/
|
*/
|
||||||
public ArrayType(final Type type, final int dimensions) {
|
public ArrayType(final Type type, final int dimensions) {
|
||||||
@@ -58,17 +58,17 @@ public final class ArrayType extends ReferenceType {
|
|||||||
throw new ClassGenException("Invalid number of dimensions: " + dimensions);
|
throw new ClassGenException("Invalid number of dimensions: " + dimensions);
|
||||||
}
|
}
|
||||||
switch (type.getType()) {
|
switch (type.getType()) {
|
||||||
case Const.T_ARRAY:
|
case Const.T_ARRAY:
|
||||||
final ArrayType array = (ArrayType) type;
|
final ArrayType array = (ArrayType) type;
|
||||||
this.dimensions = dimensions + array.dimensions;
|
this.dimensions = dimensions + array.dimensions;
|
||||||
basicType = array.basicType;
|
basicType = array.basicType;
|
||||||
break;
|
break;
|
||||||
case Const.T_VOID:
|
case Const.T_VOID:
|
||||||
throw new ClassGenException("Invalid type: void[]");
|
throw new ClassGenException("Invalid type: void[]");
|
||||||
default: // Basic type or reference
|
default: // Basic type or reference
|
||||||
this.dimensions = dimensions;
|
this.dimensions = dimensions;
|
||||||
basicType = type;
|
basicType = type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
final StringBuilder buf = new StringBuilder();
|
final StringBuilder buf = new StringBuilder();
|
||||||
for (int i = 0; i < this.dimensions; i++) {
|
for (int i = 0; i < this.dimensions; i++) {
|
||||||
|
|||||||
@@ -23,32 +23,6 @@ import haidnor.jvm.bcel.Const;
|
|||||||
*/
|
*/
|
||||||
public final class BasicType extends Type {
|
public final class BasicType extends Type {
|
||||||
|
|
||||||
// @since 6.0 no longer final
|
|
||||||
public static BasicType getType(final byte type) {
|
|
||||||
switch (type) {
|
|
||||||
case Const.T_VOID:
|
|
||||||
return VOID;
|
|
||||||
case Const.T_BOOLEAN:
|
|
||||||
return BOOLEAN;
|
|
||||||
case Const.T_BYTE:
|
|
||||||
return BYTE;
|
|
||||||
case Const.T_SHORT:
|
|
||||||
return SHORT;
|
|
||||||
case Const.T_CHAR:
|
|
||||||
return CHAR;
|
|
||||||
case Const.T_INT:
|
|
||||||
return INT;
|
|
||||||
case Const.T_LONG:
|
|
||||||
return LONG;
|
|
||||||
case Const.T_DOUBLE:
|
|
||||||
return DOUBLE;
|
|
||||||
case Const.T_FLOAT:
|
|
||||||
return FLOAT;
|
|
||||||
default:
|
|
||||||
throw new ClassGenException("Invalid type: " + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for basic types such as int, long, 'void'
|
* Constructor for basic types such as int, long, 'void'
|
||||||
*
|
*
|
||||||
@@ -62,6 +36,32 @@ public final class BasicType extends Type {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @since 6.0 no longer final
|
||||||
|
public static BasicType getType(final byte type) {
|
||||||
|
switch (type) {
|
||||||
|
case Const.T_VOID:
|
||||||
|
return VOID;
|
||||||
|
case Const.T_BOOLEAN:
|
||||||
|
return BOOLEAN;
|
||||||
|
case Const.T_BYTE:
|
||||||
|
return BYTE;
|
||||||
|
case Const.T_SHORT:
|
||||||
|
return SHORT;
|
||||||
|
case Const.T_CHAR:
|
||||||
|
return CHAR;
|
||||||
|
case Const.T_INT:
|
||||||
|
return INT;
|
||||||
|
case Const.T_LONG:
|
||||||
|
return LONG;
|
||||||
|
case Const.T_DOUBLE:
|
||||||
|
return DOUBLE;
|
||||||
|
case Const.T_FLOAT:
|
||||||
|
return FLOAT;
|
||||||
|
default:
|
||||||
|
throw new ClassGenException("Invalid type: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if both type objects refer to the same type
|
* @return true if both type objects refer to the same type
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,13 +26,6 @@ package haidnor.jvm.bcel.generic;
|
|||||||
*/
|
*/
|
||||||
public final class BranchHandle extends InstructionHandle {
|
public final class BranchHandle extends InstructionHandle {
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory method.
|
|
||||||
*/
|
|
||||||
static BranchHandle getBranchHandle(final BranchInstruction i) {
|
|
||||||
return new BranchHandle(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is also a cache in case the InstructionHandle#swapInstruction() method is used
|
// This is also a cache in case the InstructionHandle#swapInstruction() method is used
|
||||||
// See BCEL-273
|
// See BCEL-273
|
||||||
private BranchInstruction bi; // An alias in fact, but saves lots of casts
|
private BranchInstruction bi; // An alias in fact, but saves lots of casts
|
||||||
@@ -42,6 +35,13 @@ public final class BranchHandle extends InstructionHandle {
|
|||||||
bi = i;
|
bi = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method.
|
||||||
|
*/
|
||||||
|
static BranchHandle getBranchHandle(final BranchInstruction i) {
|
||||||
|
return new BranchHandle(i);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private
|
* Override InstructionHandle methods: delegate to branch instruction. Through this overriding all access to the private
|
||||||
* i_position field should be prevented.
|
* i_position field should be prevented.
|
||||||
@@ -51,6 +51,13 @@ public final class BranchHandle extends InstructionHandle {
|
|||||||
return bi.getPosition();
|
return bi.getPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void setPosition(final int pos) {
|
||||||
|
// Original code: i_position = bi.position = pos;
|
||||||
|
bi.setPosition(pos);
|
||||||
|
super.setPosition(pos);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return target of instruction.
|
* @return target of instruction.
|
||||||
*/
|
*/
|
||||||
@@ -58,6 +65,13 @@ public final class BranchHandle extends InstructionHandle {
|
|||||||
return bi.getTarget();
|
return bi.getTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pass new target to instruction.
|
||||||
|
*/
|
||||||
|
public void setTarget(final InstructionHandle ih) {
|
||||||
|
bi.setTarget(ih);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set new contents. Old instruction is disposed and may not be used anymore.
|
* Set new contents. Old instruction is disposed and may not be used anymore.
|
||||||
*/
|
*/
|
||||||
@@ -70,20 +84,6 @@ public final class BranchHandle extends InstructionHandle {
|
|||||||
bi = (BranchInstruction) i;
|
bi = (BranchInstruction) i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
void setPosition(final int pos) {
|
|
||||||
// Original code: i_position = bi.position = pos;
|
|
||||||
bi.setPosition(pos);
|
|
||||||
super.setPosition(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pass new target to instruction.
|
|
||||||
*/
|
|
||||||
public void setTarget(final InstructionHandle ih) {
|
|
||||||
bi.setTarget(ih);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int updatePosition(final int offset, final int maxOffset) {
|
protected int updatePosition(final int offset, final int maxOffset) {
|
||||||
final int x = bi.updatePosition(offset, maxOffset);
|
final int x = bi.updatePosition(offset, maxOffset);
|
||||||
|
|||||||
@@ -29,30 +29,16 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
|
public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
|
||||||
|
|
||||||
/**
|
|
||||||
* Used by BranchInstruction, LocalVariableGen, CodeExceptionGen, LineNumberGen
|
|
||||||
*/
|
|
||||||
static void notifyTarget(final InstructionHandle oldIh, final InstructionHandle newIh, final InstructionTargeter t) {
|
|
||||||
if (oldIh != null) {
|
|
||||||
oldIh.removeTargeter(t);
|
|
||||||
}
|
|
||||||
if (newIh != null) {
|
|
||||||
newIh.addTargeter(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected int index; // Branch target relative to this instruction
|
protected int index; // Branch target relative to this instruction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected InstructionHandle target; // Target object in instruction list
|
protected InstructionHandle target; // Target object in instruction list
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +62,18 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
setTarget(target);
|
setTarget(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by BranchInstruction, LocalVariableGen, CodeExceptionGen, LineNumberGen
|
||||||
|
*/
|
||||||
|
static void notifyTarget(final InstructionHandle oldIh, final InstructionHandle newIh, final InstructionTargeter t) {
|
||||||
|
if (oldIh != null) {
|
||||||
|
oldIh.removeTargeter(t);
|
||||||
|
}
|
||||||
|
if (newIh != null) {
|
||||||
|
newIh.addTargeter(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true, if ih is target of this instruction
|
* @return true, if ih is target of this instruction
|
||||||
*/
|
*/
|
||||||
@@ -116,6 +114,14 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index the index to set
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
|
protected void setIndex(final int index) {
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the position
|
* @return the position
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
@@ -124,6 +130,14 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param position the position to set
|
||||||
|
* @since 6.0
|
||||||
|
*/
|
||||||
|
protected void setPosition(final int position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return target of branch instruction
|
* @return target of branch instruction
|
||||||
*/
|
*/
|
||||||
@@ -131,6 +145,16 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set branch target
|
||||||
|
*
|
||||||
|
* @param target branch target
|
||||||
|
*/
|
||||||
|
public void setTarget(final InstructionHandle target) {
|
||||||
|
notifyTarget(this.target, target, this);
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the offset to this instruction's target
|
* @return the offset to this instruction's target
|
||||||
*/
|
*/
|
||||||
@@ -157,7 +181,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
* Read needed data (e.g. index) from file. Conversion to a InstructionHandle is done in InstructionList(byte[]).
|
* Read needed data (e.g. index) from file. Conversion to a InstructionHandle is done in InstructionList(byte[]).
|
||||||
*
|
*
|
||||||
* @param bytes input stream
|
* @param bytes input stream
|
||||||
* @param wide wide prefix?
|
* @param wide wide prefix?
|
||||||
* @see InstructionList
|
* @see InstructionList
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@@ -166,35 +190,9 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
index = bytes.readShort();
|
index = bytes.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param index the index to set
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
protected void setIndex(final int index) {
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param position the position to set
|
|
||||||
* @since 6.0
|
|
||||||
*/
|
|
||||||
protected void setPosition(final int position) {
|
|
||||||
this.position = position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set branch target
|
|
||||||
*
|
|
||||||
* @param target branch target
|
|
||||||
*/
|
|
||||||
public void setTarget(final InstructionHandle target) {
|
|
||||||
notifyTarget(this.target, target, this);
|
|
||||||
this.target = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Long output format:
|
* Long output format:
|
||||||
*
|
* <p>
|
||||||
* <position in byte code> <name of opcode> "["<opcode number>"]" "("<length of instruction>")"
|
* <position in byte code> <name of opcode> "["<opcode number>"]" "("<length of instruction>")"
|
||||||
* "<"<target instruction>">" "@"<branch target offset>
|
* "<"<target instruction>">" "@"<branch target offset>
|
||||||
*
|
*
|
||||||
@@ -232,7 +230,7 @@ public abstract class BranchInstruction extends Instruction implements Instructi
|
|||||||
* length instructions 'setPositions' performs multiple passes over the instruction list to calculate the correct (byte)
|
* length instructions 'setPositions' performs multiple passes over the instruction list to calculate the correct (byte)
|
||||||
* positions and offsets by calling this function.
|
* positions and offsets by calling this function.
|
||||||
*
|
*
|
||||||
* @param offset additional offset caused by preceding (variable length) instructions
|
* @param offset additional offset caused by preceding (variable length) instructions
|
||||||
* @param maxOffset the maximum offset that may be caused by these instructions
|
* @param maxOffset the maximum offset that may be caused by these instructions
|
||||||
* @return additional offset caused by possible change of this instruction's length
|
* @return additional offset caused by possible change of this instruction's length
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -74,6 +74,19 @@ public abstract class CPInstruction extends Instruction implements TypedInstruct
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the index to constant pool.
|
||||||
|
*
|
||||||
|
* @param index in constant pool.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setIndex(final int index) { // TODO could be package-protected?
|
||||||
|
if (index < 0) {
|
||||||
|
throw new ClassGenException("Negative index value: " + index);
|
||||||
|
}
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return type related with this instruction.
|
* @return type related with this instruction.
|
||||||
*/
|
*/
|
||||||
@@ -91,7 +104,7 @@ public abstract class CPInstruction extends Instruction implements TypedInstruct
|
|||||||
* Read needed data (i.e., index) from file.
|
* Read needed data (i.e., index) from file.
|
||||||
*
|
*
|
||||||
* @param bytes input stream
|
* @param bytes input stream
|
||||||
* @param wide wide prefix?
|
* @param wide wide prefix?
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
|
protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
|
||||||
@@ -99,22 +112,9 @@ public abstract class CPInstruction extends Instruction implements TypedInstruct
|
|||||||
super.setLength(3);
|
super.setLength(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the index to constant pool.
|
|
||||||
*
|
|
||||||
* @param index in constant pool.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void setIndex(final int index) { // TODO could be package-protected?
|
|
||||||
if (index < 0) {
|
|
||||||
throw new ClassGenException("Negative index value: " + index);
|
|
||||||
}
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Long output format:
|
* Long output format:
|
||||||
*
|
* <p>
|
||||||
* <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool
|
* <name of opcode> "["<opcode number>"]" "("<length of instruction>")" "<"< constant pool
|
||||||
* index>">"
|
* index>">"
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -45,42 +45,23 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
return THIS.getClassName().hashCode();
|
return THIS.getClassName().hashCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private final String fileName;
|
||||||
/**
|
// ArrayLists instead of arrays to gather fields, methods, etc.
|
||||||
* @return Comparison strategy object
|
private final List<JavaField> fieldList = new ArrayList<>();
|
||||||
*/
|
private final List<JavaMethod> methodList = new ArrayList<>();
|
||||||
public static BCELComparator getComparator() {
|
private final List<Attribute> attributeList = new ArrayList<>();
|
||||||
return bcelComparator;
|
private final List<String> interfaceList = new ArrayList<>();
|
||||||
}
|
private final List<AnnotationEntryGen> annotationList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
|
||||||
* @param comparator Comparison strategy object
|
|
||||||
*/
|
|
||||||
public static void setComparator(final BCELComparator comparator) {
|
|
||||||
bcelComparator = comparator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Corresponds to the fields found in a JavaClass object.
|
* Corresponds to the fields found in a JavaClass object.
|
||||||
*/
|
*/
|
||||||
private String className;
|
private String className;
|
||||||
private String superClassName;
|
private String superClassName;
|
||||||
private final String fileName;
|
|
||||||
private int classNameIndex = -1;
|
private int classNameIndex = -1;
|
||||||
private int superclassNameIndex = -1;
|
private int superclassNameIndex = -1;
|
||||||
private int major = Const.MAJOR_1_1;
|
private int major = Const.MAJOR_1_1;
|
||||||
private int minor = Const.MINOR_1_1;
|
private int minor = Const.MINOR_1_1;
|
||||||
private ConstantPoolGen cp; // Template for building up constant pool
|
private ConstantPoolGen cp; // Template for building up constant pool
|
||||||
// ArrayLists instead of arrays to gather fields, methods, etc.
|
|
||||||
private final List<JavaField> fieldList = new ArrayList<>();
|
|
||||||
private final List<JavaMethod> methodList = new ArrayList<>();
|
|
||||||
|
|
||||||
private final List<Attribute> attributeList = new ArrayList<>();
|
|
||||||
|
|
||||||
private final List<String> interfaceList = new ArrayList<>();
|
|
||||||
|
|
||||||
private final List<AnnotationEntryGen> annotationList = new ArrayList<>();
|
|
||||||
|
|
||||||
private List<ClassObserver> observers;
|
private List<ClassObserver> observers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,11 +96,11 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
/**
|
/**
|
||||||
* Convenience constructor to set up some important values initially.
|
* Convenience constructor to set up some important values initially.
|
||||||
*
|
*
|
||||||
* @param className fully qualified class name
|
* @param className fully qualified class name
|
||||||
* @param superClassName fully qualified superclass name
|
* @param superClassName fully qualified superclass name
|
||||||
* @param fileName source file name
|
* @param fileName source file name
|
||||||
* @param accessFlags access qualifiers
|
* @param accessFlags access qualifiers
|
||||||
* @param interfaces implemented interfaces
|
* @param interfaces implemented interfaces
|
||||||
*/
|
*/
|
||||||
public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces) {
|
public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces) {
|
||||||
this(className, superClassName, fileName, accessFlags, interfaces, new ConstantPoolGen());
|
this(className, superClassName, fileName, accessFlags, interfaces, new ConstantPoolGen());
|
||||||
@@ -128,15 +109,15 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
/**
|
/**
|
||||||
* Convenience constructor to set up some important values initially.
|
* Convenience constructor to set up some important values initially.
|
||||||
*
|
*
|
||||||
* @param className fully qualified class name
|
* @param className fully qualified class name
|
||||||
* @param superClassName fully qualified superclass name
|
* @param superClassName fully qualified superclass name
|
||||||
* @param fileName source file name
|
* @param fileName source file name
|
||||||
* @param accessFlags access qualifiers
|
* @param accessFlags access qualifiers
|
||||||
* @param interfaces implemented interfaces
|
* @param interfaces implemented interfaces
|
||||||
* @param cp constant pool to use
|
* @param cp constant pool to use
|
||||||
*/
|
*/
|
||||||
public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces,
|
public ClassGen(final String className, final String superClassName, final String fileName, final int accessFlags, final String[] interfaces,
|
||||||
final ConstantPoolGen cp) {
|
final ConstantPoolGen cp) {
|
||||||
super(accessFlags);
|
super(accessFlags);
|
||||||
this.className = className;
|
this.className = className;
|
||||||
this.superClassName = superClassName;
|
this.superClassName = superClassName;
|
||||||
@@ -153,6 +134,20 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Comparison strategy object
|
||||||
|
*/
|
||||||
|
public static BCELComparator getComparator() {
|
||||||
|
return bcelComparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param comparator Comparison strategy object
|
||||||
|
*/
|
||||||
|
public static void setComparator(final BCELComparator comparator) {
|
||||||
|
bcelComparator = comparator;
|
||||||
|
}
|
||||||
|
|
||||||
public void addAnnotationEntry(final AnnotationEntryGen a) {
|
public void addAnnotationEntry(final AnnotationEntryGen a) {
|
||||||
annotationList.add(a);
|
annotationList.add(a);
|
||||||
}
|
}
|
||||||
@@ -168,7 +163,7 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience method.
|
* Convenience method.
|
||||||
*
|
* <p>
|
||||||
* Add an empty constructor to this class that does nothing but calling super().
|
* Add an empty constructor to this class that does nothing but calling super().
|
||||||
*
|
*
|
||||||
* @param accessFlags rights for constructor
|
* @param accessFlags rights for constructor
|
||||||
@@ -281,14 +276,28 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
return className;
|
return className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setClassName(final String name) {
|
||||||
|
className = Utility.pathToPackage(name);
|
||||||
|
classNameIndex = cp.addClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
public int getClassNameIndex() {
|
public int getClassNameIndex() {
|
||||||
return classNameIndex;
|
return classNameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setClassNameIndex(final int classNameIndex) {
|
||||||
|
this.classNameIndex = classNameIndex;
|
||||||
|
this.className = Utility.pathToPackage(cp.getConstantPool().getConstantString(classNameIndex, Const.CONSTANT_Class));
|
||||||
|
}
|
||||||
|
|
||||||
public ConstantPoolGen getConstantPool() {
|
public ConstantPoolGen getConstantPool() {
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConstantPool(final ConstantPoolGen constantPool) {
|
||||||
|
cp = constantPool;
|
||||||
|
}
|
||||||
|
|
||||||
public JavaField[] getFields() {
|
public JavaField[] getFields() {
|
||||||
return fieldList.toArray(JavaField.EMPTY_ARRAY);
|
return fieldList.toArray(JavaField.EMPTY_ARRAY);
|
||||||
}
|
}
|
||||||
@@ -328,7 +337,7 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
// Must be last since the above calls may still add something to it
|
// Must be last since the above calls may still add something to it
|
||||||
final ConstantPool cp = this.cp.getFinalConstantPool();
|
final ConstantPool cp = this.cp.getFinalConstantPool();
|
||||||
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, super.getAccessFlags(), cp, interfaces, fields, methods,
|
return new JavaClass(classNameIndex, superclassNameIndex, fileName, major, minor, super.getAccessFlags(), cp, interfaces, fields, methods,
|
||||||
attributes);
|
attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -338,6 +347,15 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
return major;
|
return major;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set major version number of class file, default value is 45 (JDK 1.1)
|
||||||
|
*
|
||||||
|
* @param major major version number
|
||||||
|
*/
|
||||||
|
public void setMajor(final int major) { // TODO could be package-protected - only called by test code
|
||||||
|
this.major = major;
|
||||||
|
}
|
||||||
|
|
||||||
public JavaMethod getMethodAt(final int pos) {
|
public JavaMethod getMethodAt(final int pos) {
|
||||||
return methodList.get(pos);
|
return methodList.get(pos);
|
||||||
}
|
}
|
||||||
@@ -346,6 +364,11 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
return methodList.toArray(JavaMethod.EMPTY_ARRAY);
|
return methodList.toArray(JavaMethod.EMPTY_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMethods(final JavaMethod[] methods) {
|
||||||
|
methodList.clear();
|
||||||
|
Collections.addAll(methodList, methods);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return minor version number of class file
|
* @return minor version number of class file
|
||||||
*/
|
*/
|
||||||
@@ -353,14 +376,33 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
return minor;
|
return minor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set minor version number of class file, default value is 3 (JDK 1.1)
|
||||||
|
*
|
||||||
|
* @param minor minor version number
|
||||||
|
*/
|
||||||
|
public void setMinor(final int minor) { // TODO could be package-protected - only called by test code
|
||||||
|
this.minor = minor;
|
||||||
|
}
|
||||||
|
|
||||||
public String getSuperclassName() {
|
public String getSuperclassName() {
|
||||||
return superClassName;
|
return superClassName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSuperclassName(final String name) {
|
||||||
|
superClassName = Utility.pathToPackage(name);
|
||||||
|
superclassNameIndex = cp.addClass(name);
|
||||||
|
}
|
||||||
|
|
||||||
public int getSuperclassNameIndex() {
|
public int getSuperclassNameIndex() {
|
||||||
return superclassNameIndex;
|
return superclassNameIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSuperclassNameIndex(final int superclassNameIndex) {
|
||||||
|
this.superclassNameIndex = superclassNameIndex;
|
||||||
|
superClassName = Utility.pathToPackage(cp.getConstantPool().getConstantString(superclassNameIndex, Const.CONSTANT_Class));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
|
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name.
|
||||||
*
|
*
|
||||||
@@ -446,57 +488,10 @@ public class ClassGen extends AccessFlags implements Cloneable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setClassName(final String name) {
|
|
||||||
className = Utility.pathToPackage(name);
|
|
||||||
classNameIndex = cp.addClass(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClassNameIndex(final int classNameIndex) {
|
|
||||||
this.classNameIndex = classNameIndex;
|
|
||||||
this.className = Utility.pathToPackage(cp.getConstantPool().getConstantString(classNameIndex, Const.CONSTANT_Class));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConstantPool(final ConstantPoolGen constantPool) {
|
|
||||||
cp = constantPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set major version number of class file, default value is 45 (JDK 1.1)
|
|
||||||
*
|
|
||||||
* @param major major version number
|
|
||||||
*/
|
|
||||||
public void setMajor(final int major) { // TODO could be package-protected - only called by test code
|
|
||||||
this.major = major;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMethodAt(final JavaMethod method, final int pos) {
|
public void setMethodAt(final JavaMethod method, final int pos) {
|
||||||
methodList.set(pos, method);
|
methodList.set(pos, method);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMethods(final JavaMethod[] methods) {
|
|
||||||
methodList.clear();
|
|
||||||
Collections.addAll(methodList, methods);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set minor version number of class file, default value is 3 (JDK 1.1)
|
|
||||||
*
|
|
||||||
* @param minor minor version number
|
|
||||||
*/
|
|
||||||
public void setMinor(final int minor) { // TODO could be package-protected - only called by test code
|
|
||||||
this.minor = minor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSuperclassName(final String name) {
|
|
||||||
superClassName = Utility.pathToPackage(name);
|
|
||||||
superclassNameIndex = cp.addClass(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSuperclassNameIndex(final int superclassNameIndex) {
|
|
||||||
this.superclassNameIndex = superclassNameIndex;
|
|
||||||
superClassName = Utility.pathToPackage(cp.getConstantPool().getConstantString(superclassNameIndex, Const.CONSTANT_Class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look for attributes representing annotations and unpack them.
|
* Look for attributes representing annotations and unpack them.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
* Add an exception handler, i.e., specify region where a handler is active and an instruction where the actual handling
|
* Add an exception handler, i.e., specify region where a handler is active and an instruction where the actual handling
|
||||||
* is done.
|
* is done.
|
||||||
*
|
*
|
||||||
* @param startPc Start of handled region (inclusive)
|
* @param startPc Start of handled region (inclusive)
|
||||||
* @param endPc End of handled region (inclusive)
|
* @param endPc End of handled region (inclusive)
|
||||||
* @param handlerPc Where handling is done
|
* @param handlerPc Where handling is done
|
||||||
* @param catchType which exception is handled, null for ANY
|
* @param catchType which exception is handled, null for ANY
|
||||||
*/
|
*/
|
||||||
@@ -71,14 +71,23 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
return startPc == ih || endPc == ih || handlerPc == ih;
|
return startPc == ih || endPc == ih || handlerPc == ih;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the type of the Exception to catch, 'null' for ANY. */
|
/**
|
||||||
|
* Gets the type of the Exception to catch, 'null' for ANY.
|
||||||
|
*/
|
||||||
public ObjectType getCatchType() {
|
public ObjectType getCatchType() {
|
||||||
return catchType;
|
return catchType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the type of the Exception to catch. Set 'null' for ANY.
|
||||||
|
*/
|
||||||
|
public void setCatchType(final ObjectType catchType) {
|
||||||
|
this.catchType = catchType;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get CodeException object.<BR>
|
* Get CodeException object.<BR>
|
||||||
*
|
* <p>
|
||||||
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
|
* This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
|
||||||
* has been called for the instruction list.
|
* has been called for the instruction list.
|
||||||
*
|
*
|
||||||
@@ -86,7 +95,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
*/
|
*/
|
||||||
public CodeException getCodeException(final ConstantPoolGen cp) {
|
public CodeException getCodeException(final ConstantPoolGen cp) {
|
||||||
return new CodeException(startPc.getPosition(), endPc.getPosition() + endPc.getInstruction().getLength(), handlerPc.getPosition(),
|
return new CodeException(startPc.getPosition(), endPc.getPosition() + endPc.getInstruction().getLength(), handlerPc.getPosition(),
|
||||||
catchType == null ? 0 : cp.addClass(catchType));
|
catchType == null ? 0 : cp.addClass(catchType));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,25 +105,6 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
return endPc;
|
return endPc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return start of handler
|
|
||||||
*/
|
|
||||||
public InstructionHandle getHandlerPC() {
|
|
||||||
return handlerPc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return start of handled region (inclusive)
|
|
||||||
*/
|
|
||||||
public InstructionHandle getStartPC() {
|
|
||||||
return startPc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the type of the Exception to catch. Set 'null' for ANY. */
|
|
||||||
public void setCatchType(final ObjectType catchType) {
|
|
||||||
this.catchType = catchType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set end of handler
|
* Set end of handler
|
||||||
*
|
*
|
||||||
@@ -125,6 +115,13 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
this.endPc = endPc;
|
this.endPc = endPc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return start of handler
|
||||||
|
*/
|
||||||
|
public InstructionHandle getHandlerPC() {
|
||||||
|
return handlerPc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set handler code
|
* Set handler code
|
||||||
*
|
*
|
||||||
@@ -135,6 +132,13 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable {
|
|||||||
this.handlerPc = handlerPc;
|
this.handlerPc = handlerPc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return start of handled region (inclusive)
|
||||||
|
*/
|
||||||
|
public InstructionHandle getStartPC() {
|
||||||
|
return startPc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set start of handler
|
* Set start of handler
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ package haidnor.jvm.bcel.generic;
|
|||||||
* meaning. For example, the (virtual) PUSH instruction takes an arbitrary argument and produces the appropriate code at
|
* meaning. For example, the (virtual) PUSH instruction takes an arbitrary argument and produces the appropriate code at
|
||||||
* dump time (ICONST, LDC, BIPUSH, ...). Also you can use the SWITCH instruction as a useful template for either
|
* dump time (ICONST, LDC, BIPUSH, ...). Also you can use the SWITCH instruction as a useful template for either
|
||||||
* LOOKUPSWITCH or TABLESWITCH.
|
* LOOKUPSWITCH or TABLESWITCH.
|
||||||
*
|
* <p>
|
||||||
* The interface provides the possibility for the user to write 'templates' or 'macros' for such reusable code patterns.
|
* The interface provides the possibility for the user to write 'templates' or 'macros' for such reusable code patterns.
|
||||||
*
|
*
|
||||||
* @see PUSH
|
* @see PUSH
|
||||||
|
|||||||
@@ -44,35 +44,27 @@ public class ConstantPoolGen {
|
|||||||
private static final String FIELDREF_DELIM = "&";
|
private static final String FIELDREF_DELIM = "&";
|
||||||
|
|
||||||
private static final String NAT_DELIM = "%"; // Name and Type
|
private static final String NAT_DELIM = "%"; // Name and Type
|
||||||
|
private final Map<String, Integer> stringTable = new HashMap<>();
|
||||||
|
private final Map<String, Integer> classTable = new HashMap<>();
|
||||||
|
private final Map<String, Integer> utf8Table = new HashMap<>();
|
||||||
|
private final Map<String, Integer> natTable = new HashMap<>();
|
||||||
|
private final Map<String, Integer> cpTable = new HashMap<>();
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected int size;
|
protected int size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected Constant[] constants;
|
protected Constant[] constants;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getSize()
|
* @deprecated (since 6.0) will be made private; do not access directly, use getSize()
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected int index = 1; // First entry (0) used by JVM
|
protected int index = 1; // First entry (0) used by JVM
|
||||||
|
|
||||||
private final Map<String, Integer> stringTable = new HashMap<>();
|
|
||||||
|
|
||||||
private final Map<String, Integer> classTable = new HashMap<>();
|
|
||||||
|
|
||||||
private final Map<String, Integer> utf8Table = new HashMap<>();
|
|
||||||
|
|
||||||
private final Map<String, Integer> natTable = new HashMap<>();
|
|
||||||
|
|
||||||
private final Map<String, Integer> cpTable = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new empty constant pool.
|
* Constructs a new empty constant pool.
|
||||||
*/
|
*/
|
||||||
@@ -255,63 +247,63 @@ public class ConstantPoolGen {
|
|||||||
* Adds a constant from another ConstantPool and returns the new index.
|
* Adds a constant from another ConstantPool and returns the new index.
|
||||||
*
|
*
|
||||||
* @param constant The constant to add.
|
* @param constant The constant to add.
|
||||||
* @param cpGen Source pool.
|
* @param cpGen Source pool.
|
||||||
* @return index of entry
|
* @return index of entry
|
||||||
*/
|
*/
|
||||||
public int addConstant(final Constant constant, final ConstantPoolGen cpGen) {
|
public int addConstant(final Constant constant, final ConstantPoolGen cpGen) {
|
||||||
final Constant[] constants = cpGen.getConstantPool().getConstantPool();
|
final Constant[] constants = cpGen.getConstantPool().getConstantPool();
|
||||||
switch (constant.getTag()) {
|
switch (constant.getTag()) {
|
||||||
case Const.CONSTANT_String: {
|
case Const.CONSTANT_String: {
|
||||||
final ConstantString s = (ConstantString) constant;
|
final ConstantString s = (ConstantString) constant;
|
||||||
final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
|
final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getStringIndex()];
|
||||||
return addString(u8.getBytes());
|
return addString(u8.getBytes());
|
||||||
}
|
}
|
||||||
case Const.CONSTANT_Class: {
|
case Const.CONSTANT_Class: {
|
||||||
final ConstantClass s = (ConstantClass) constant;
|
final ConstantClass s = (ConstantClass) constant;
|
||||||
final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
|
final ConstantUtf8 u8 = (ConstantUtf8) constants[s.getNameIndex()];
|
||||||
return addClass(u8.getBytes());
|
return addClass(u8.getBytes());
|
||||||
}
|
}
|
||||||
case Const.CONSTANT_NameAndType: {
|
case Const.CONSTANT_NameAndType: {
|
||||||
final ConstantNameAndType n = (ConstantNameAndType) constant;
|
final ConstantNameAndType n = (ConstantNameAndType) constant;
|
||||||
final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
|
final ConstantUtf8 u8 = (ConstantUtf8) constants[n.getNameIndex()];
|
||||||
final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
|
final ConstantUtf8 u8_2 = (ConstantUtf8) constants[n.getSignatureIndex()];
|
||||||
return addNameAndType(u8.getBytes(), u8_2.getBytes());
|
return addNameAndType(u8.getBytes(), u8_2.getBytes());
|
||||||
}
|
}
|
||||||
case Const.CONSTANT_Utf8:
|
case Const.CONSTANT_Utf8:
|
||||||
return addUtf8(((ConstantUtf8) constant).getBytes());
|
return addUtf8(((ConstantUtf8) constant).getBytes());
|
||||||
case Const.CONSTANT_Double:
|
case Const.CONSTANT_Double:
|
||||||
return addDouble(((ConstantDouble) constant).getBytes());
|
return addDouble(((ConstantDouble) constant).getBytes());
|
||||||
case Const.CONSTANT_Float:
|
case Const.CONSTANT_Float:
|
||||||
return addFloat(((ConstantFloat) constant).getBytes());
|
return addFloat(((ConstantFloat) constant).getBytes());
|
||||||
case Const.CONSTANT_Long:
|
case Const.CONSTANT_Long:
|
||||||
return addLong(((ConstantLong) constant).getBytes());
|
return addLong(((ConstantLong) constant).getBytes());
|
||||||
case Const.CONSTANT_Integer:
|
case Const.CONSTANT_Integer:
|
||||||
return addInteger(((ConstantInteger) constant).getBytes());
|
return addInteger(((ConstantInteger) constant).getBytes());
|
||||||
case Const.CONSTANT_InterfaceMethodref:
|
|
||||||
case Const.CONSTANT_Methodref:
|
|
||||||
case Const.CONSTANT_Fieldref: {
|
|
||||||
final ConstantCP m = (ConstantCP) constant;
|
|
||||||
final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
|
|
||||||
final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
|
|
||||||
ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
|
|
||||||
final String className = Utility.pathToPackage(u8.getBytes());
|
|
||||||
u8 = (ConstantUtf8) constants[n.getNameIndex()];
|
|
||||||
final String name = u8.getBytes();
|
|
||||||
u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
|
|
||||||
final String signature = u8.getBytes();
|
|
||||||
switch (constant.getTag()) {
|
|
||||||
case Const.CONSTANT_InterfaceMethodref:
|
case Const.CONSTANT_InterfaceMethodref:
|
||||||
return addInterfaceMethodref(className, name, signature);
|
|
||||||
case Const.CONSTANT_Methodref:
|
case Const.CONSTANT_Methodref:
|
||||||
return addMethodref(className, name, signature);
|
case Const.CONSTANT_Fieldref: {
|
||||||
case Const.CONSTANT_Fieldref:
|
final ConstantCP m = (ConstantCP) constant;
|
||||||
return addFieldref(className, name, signature);
|
final ConstantClass clazz = (ConstantClass) constants[m.getClassIndex()];
|
||||||
|
final ConstantNameAndType n = (ConstantNameAndType) constants[m.getNameAndTypeIndex()];
|
||||||
|
ConstantUtf8 u8 = (ConstantUtf8) constants[clazz.getNameIndex()];
|
||||||
|
final String className = Utility.pathToPackage(u8.getBytes());
|
||||||
|
u8 = (ConstantUtf8) constants[n.getNameIndex()];
|
||||||
|
final String name = u8.getBytes();
|
||||||
|
u8 = (ConstantUtf8) constants[n.getSignatureIndex()];
|
||||||
|
final String signature = u8.getBytes();
|
||||||
|
switch (constant.getTag()) {
|
||||||
|
case Const.CONSTANT_InterfaceMethodref:
|
||||||
|
return addInterfaceMethodref(className, name, signature);
|
||||||
|
case Const.CONSTANT_Methodref:
|
||||||
|
return addMethodref(className, name, signature);
|
||||||
|
case Const.CONSTANT_Fieldref:
|
||||||
|
return addFieldref(className, name, signature);
|
||||||
|
default: // Never reached
|
||||||
|
throw new IllegalArgumentException("Unknown constant type " + constant);
|
||||||
|
}
|
||||||
|
}
|
||||||
default: // Never reached
|
default: // Never reached
|
||||||
throw new IllegalArgumentException("Unknown constant type " + constant);
|
throw new IllegalArgumentException("Unknown constant type " + constant);
|
||||||
}
|
|
||||||
}
|
|
||||||
default: // Never reached
|
|
||||||
throw new IllegalArgumentException("Unknown constant type " + constant);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,9 +387,9 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there.
|
* Add a new InterfaceMethodref constant to the ConstantPool, if it is not already in there.
|
||||||
*
|
*
|
||||||
* @param className class name string to add
|
* @param className class name string to add
|
||||||
* @param methodName method name string to add
|
* @param methodName method name string to add
|
||||||
* @param signature signature string to add
|
* @param signature signature string to add
|
||||||
* @return index of entry
|
* @return index of entry
|
||||||
*/
|
*/
|
||||||
public int addInterfaceMethodref(final String className, final String methodName, final String signature) {
|
public int addInterfaceMethodref(final String className, final String methodName, final String signature) {
|
||||||
@@ -430,6 +422,7 @@ public class ConstantPoolGen {
|
|||||||
index += 2; // Wastes one entry according to spec
|
index += 2; // Wastes one entry according to spec
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int addMethodref(final MethodGen method) {
|
public int addMethodref(final MethodGen method) {
|
||||||
return addMethodref(method.getClassName(), method.getName(), method.getSignature());
|
return addMethodref(method.getClassName(), method.getName(), method.getSignature());
|
||||||
}
|
}
|
||||||
@@ -437,9 +430,9 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Add a new Methodref constant to the ConstantPool, if it is not already in there.
|
* Add a new Methodref constant to the ConstantPool, if it is not already in there.
|
||||||
*
|
*
|
||||||
* @param className class name string to add
|
* @param className class name string to add
|
||||||
* @param methodName method name string to add
|
* @param methodName method name string to add
|
||||||
* @param signature method signature string to add
|
* @param signature method signature string to add
|
||||||
* @return index of entry
|
* @return index of entry
|
||||||
*/
|
*/
|
||||||
public int addMethodref(final String className, final String methodName, final String signature) {
|
public int addMethodref(final String className, final String methodName, final String signature) {
|
||||||
@@ -458,7 +451,7 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Add a new NameAndType constant to the ConstantPool if it is not already in there.
|
* Add a new NameAndType constant to the ConstantPool if it is not already in there.
|
||||||
*
|
*
|
||||||
* @param name Name string to add
|
* @param name Name string to add
|
||||||
* @param signature signature string to add
|
* @param signature signature string to add
|
||||||
* @return index of entry
|
* @return index of entry
|
||||||
*/
|
*/
|
||||||
@@ -654,9 +647,9 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Look for ConstantInterfaceMethodref in ConstantPool.
|
* Look for ConstantInterfaceMethodref in ConstantPool.
|
||||||
*
|
*
|
||||||
* @param className Where to find method
|
* @param className Where to find method
|
||||||
* @param methodName Guess what
|
* @param methodName Guess what
|
||||||
* @param signature return and argument types
|
* @param signature return and argument types
|
||||||
* @return index on success, -1 otherwise
|
* @return index on success, -1 otherwise
|
||||||
*/
|
*/
|
||||||
public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) {
|
public int lookupInterfaceMethodref(final String className, final String methodName, final String signature) {
|
||||||
@@ -688,9 +681,9 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Look for ConstantMethodref in ConstantPool.
|
* Look for ConstantMethodref in ConstantPool.
|
||||||
*
|
*
|
||||||
* @param className Where to find method
|
* @param className Where to find method
|
||||||
* @param methodName Guess what
|
* @param methodName Guess what
|
||||||
* @param signature return and argument types
|
* @param signature return and argument types
|
||||||
* @return index on success, -1 otherwise
|
* @return index on success, -1 otherwise
|
||||||
*/
|
*/
|
||||||
public int lookupMethodref(final String className, final String methodName, final String signature) {
|
public int lookupMethodref(final String className, final String methodName, final String signature) {
|
||||||
@@ -700,7 +693,7 @@ public class ConstantPoolGen {
|
|||||||
/**
|
/**
|
||||||
* Look for ConstantNameAndType in ConstantPool.
|
* Look for ConstantNameAndType in ConstantPool.
|
||||||
*
|
*
|
||||||
* @param name of variable/method
|
* @param name of variable/method
|
||||||
* @param signature of variable/method
|
* @param signature of variable/method
|
||||||
* @return index on success, -1 otherwise
|
* @return index on success, -1 otherwise
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package haidnor.jvm.bcel.generic;
|
|||||||
/**
|
/**
|
||||||
* Denotes a push instruction that produces a literal on the stack such as SIPUSH, BIPUSH, ICONST, etc.
|
* Denotes a push instruction that produces a literal on the stack such as SIPUSH, BIPUSH, ICONST, etc.
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @see ICONST
|
* @see ICONST
|
||||||
* @see SIPUSH
|
* @see SIPUSH
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -43,30 +43,30 @@ public abstract class ConversionInstruction extends Instruction implements Typed
|
|||||||
public Type getType(final ConstantPoolGen cp) {
|
public Type getType(final ConstantPoolGen cp) {
|
||||||
final short opcode = super.getOpcode();
|
final short opcode = super.getOpcode();
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Const.D2I:
|
case Const.D2I:
|
||||||
case Const.F2I:
|
case Const.F2I:
|
||||||
case Const.L2I:
|
case Const.L2I:
|
||||||
return Type.INT;
|
return Type.INT;
|
||||||
case Const.D2F:
|
case Const.D2F:
|
||||||
case Const.I2F:
|
case Const.I2F:
|
||||||
case Const.L2F:
|
case Const.L2F:
|
||||||
return Type.FLOAT;
|
return Type.FLOAT;
|
||||||
case Const.D2L:
|
case Const.D2L:
|
||||||
case Const.F2L:
|
case Const.F2L:
|
||||||
case Const.I2L:
|
case Const.I2L:
|
||||||
return Type.LONG;
|
return Type.LONG;
|
||||||
case Const.F2D:
|
case Const.F2D:
|
||||||
case Const.I2D:
|
case Const.I2D:
|
||||||
case Const.L2D:
|
case Const.L2D:
|
||||||
return Type.DOUBLE;
|
return Type.DOUBLE;
|
||||||
case Const.I2B:
|
case Const.I2B:
|
||||||
return Type.BYTE;
|
return Type.BYTE;
|
||||||
case Const.I2C:
|
case Const.I2C:
|
||||||
return Type.CHAR;
|
return Type.CHAR;
|
||||||
case Const.I2S:
|
case Const.I2S:
|
||||||
return Type.SHORT;
|
return Type.SHORT;
|
||||||
default: // Never reached
|
default: // Never reached
|
||||||
throw new ClassGenException("Unknown type " + opcode);
|
throw new ClassGenException("Unknown type " + opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import haidnor.jvm.bcel.Const;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* ..., result.word1, result1.word2
|
* ..., result.word1, result1.word2
|
||||||
*/
|
*/
|
||||||
public class DADD extends ArithmeticInstruction {
|
public class DADD extends ArithmeticInstruction {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import haidnor.jvm.bcel.Const;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* ..., result.word1, result.word2
|
* ..., result.word1, result.word2
|
||||||
*/
|
*/
|
||||||
public class DDIV extends ArithmeticInstruction {
|
public class DDIV extends ArithmeticInstruction {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import haidnor.jvm.bcel.Const;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* ..., result.word1, result.word2
|
* ..., result.word1, result.word2
|
||||||
*/
|
*/
|
||||||
public class DMUL extends ArithmeticInstruction {
|
public class DMUL extends ArithmeticInstruction {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import haidnor.jvm.bcel.Const;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* ..., result.word1, result.word2
|
* ..., result.word1, result.word2
|
||||||
*/
|
*/
|
||||||
public class DREM extends ArithmeticInstruction {
|
public class DREM extends ArithmeticInstruction {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import haidnor.jvm.bcel.Const;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
* Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 ->
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* ..., result.word1, result.word2
|
* ..., result.word1, result.word2
|
||||||
*/
|
*/
|
||||||
public class DSUB extends ArithmeticInstruction {
|
public class DSUB extends ArithmeticInstruction {
|
||||||
|
|||||||
@@ -52,83 +52,11 @@ public abstract class ElementValueGen {
|
|||||||
public static final int PRIMITIVE_SHORT = 'S';
|
public static final int PRIMITIVE_SHORT = 'S';
|
||||||
|
|
||||||
public static final int PRIMITIVE_BOOLEAN = 'Z';
|
public static final int PRIMITIVE_BOOLEAN = 'Z';
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct.
|
|
||||||
*/
|
|
||||||
public static ElementValueGen copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
|
||||||
switch (value.getElementValueType()) {
|
|
||||||
case 'B': // byte
|
|
||||||
case 'C': // char
|
|
||||||
case 'D': // double
|
|
||||||
case 'F': // float
|
|
||||||
case 'I': // int
|
|
||||||
case 'J': // long
|
|
||||||
case 'S': // short
|
|
||||||
case 'Z': // boolean
|
|
||||||
case 's': // String
|
|
||||||
return new SimpleElementValueGen((SimpleElementValue) value, cpool, copyPoolEntries);
|
|
||||||
case 'e': // Enum constant
|
|
||||||
return new EnumElementValueGen((EnumElementValue) value, cpool, copyPoolEntries);
|
|
||||||
case '@': // Annotation
|
|
||||||
return new AnnotationElementValueGen((AnnotationElementValue) value, cpool, copyPoolEntries);
|
|
||||||
case '[': // Array
|
|
||||||
return new ArrayElementValueGen((ArrayElementValue) value, cpool, copyPoolEntries);
|
|
||||||
case 'c': // Class
|
|
||||||
return new ClassElementValueGen((ClassElementValue) value, cpool, copyPoolEntries);
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ElementValueGen readElementValue(final DataInput dis, final ConstantPoolGen cpGen) throws IOException {
|
|
||||||
final int type = dis.readUnsignedByte();
|
|
||||||
switch (type) {
|
|
||||||
case 'B': // byte
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'C': // char
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'D': // double
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'F': // float
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'I': // int
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'J': // long
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'S': // short
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'Z': // boolean
|
|
||||||
return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 's': // String
|
|
||||||
return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'e': // Enum constant
|
|
||||||
return new EnumElementValueGen(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen);
|
|
||||||
case 'c': // Class
|
|
||||||
return new ClassElementValueGen(dis.readUnsignedShort(), cpGen);
|
|
||||||
case '@': // Annotation
|
|
||||||
// TODO: isRuntimeVisible ??????????
|
|
||||||
// FIXME
|
|
||||||
return new AnnotationElementValueGen(ANNOTATION, new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen.getConstantPool(), true), cpGen, false),
|
|
||||||
cpGen);
|
|
||||||
case '[': // Array
|
|
||||||
final int numArrayVals = dis.readUnsignedShort();
|
|
||||||
final ElementValue[] evalues = new ElementValue[numArrayVals];
|
|
||||||
for (int j = 0; j < numArrayVals; j++) {
|
|
||||||
evalues[j] = ElementValue.readElementValue(dis, cpGen.getConstantPool());
|
|
||||||
}
|
|
||||||
return new ArrayElementValueGen(ARRAY, evalues, cpGen);
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected int type;
|
protected int type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
* @deprecated (since 6.0) will be made private and final; do not access directly, use getter
|
||||||
*/
|
*/
|
||||||
@@ -140,6 +68,76 @@ public abstract class ElementValueGen {
|
|||||||
this.cpGen = cpGen;
|
this.cpGen = cpGen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an (modifiable) ElementValueGen copy of an (immutable) ElementValue - constant pool is assumed correct.
|
||||||
|
*/
|
||||||
|
public static ElementValueGen copy(final ElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) {
|
||||||
|
switch (value.getElementValueType()) {
|
||||||
|
case 'B': // byte
|
||||||
|
case 'C': // char
|
||||||
|
case 'D': // double
|
||||||
|
case 'F': // float
|
||||||
|
case 'I': // int
|
||||||
|
case 'J': // long
|
||||||
|
case 'S': // short
|
||||||
|
case 'Z': // boolean
|
||||||
|
case 's': // String
|
||||||
|
return new SimpleElementValueGen((SimpleElementValue) value, cpool, copyPoolEntries);
|
||||||
|
case 'e': // Enum constant
|
||||||
|
return new EnumElementValueGen((EnumElementValue) value, cpool, copyPoolEntries);
|
||||||
|
case '@': // Annotation
|
||||||
|
return new AnnotationElementValueGen((AnnotationElementValue) value, cpool, copyPoolEntries);
|
||||||
|
case '[': // Array
|
||||||
|
return new ArrayElementValueGen((ArrayElementValue) value, cpool, copyPoolEntries);
|
||||||
|
case 'c': // Class
|
||||||
|
return new ClassElementValueGen((ClassElementValue) value, cpool, copyPoolEntries);
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("Not implemented yet! (" + value.getElementValueType() + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ElementValueGen readElementValue(final DataInput dis, final ConstantPoolGen cpGen) throws IOException {
|
||||||
|
final int type = dis.readUnsignedByte();
|
||||||
|
switch (type) {
|
||||||
|
case 'B': // byte
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_BYTE, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'C': // char
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_CHAR, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'D': // double
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_DOUBLE, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'F': // float
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_FLOAT, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'I': // int
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_INT, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'J': // long
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_LONG, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'S': // short
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_SHORT, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'Z': // boolean
|
||||||
|
return new SimpleElementValueGen(PRIMITIVE_BOOLEAN, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 's': // String
|
||||||
|
return new SimpleElementValueGen(STRING, dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'e': // Enum constant
|
||||||
|
return new EnumElementValueGen(dis.readUnsignedShort(), dis.readUnsignedShort(), cpGen);
|
||||||
|
case 'c': // Class
|
||||||
|
return new ClassElementValueGen(dis.readUnsignedShort(), cpGen);
|
||||||
|
case '@': // Annotation
|
||||||
|
// TODO: isRuntimeVisible ??????????
|
||||||
|
// FIXME
|
||||||
|
return new AnnotationElementValueGen(ANNOTATION, new AnnotationEntryGen(AnnotationEntry.read(dis, cpGen.getConstantPool(), true), cpGen, false),
|
||||||
|
cpGen);
|
||||||
|
case '[': // Array
|
||||||
|
final int numArrayVals = dis.readUnsignedShort();
|
||||||
|
final ElementValue[] evalues = new ElementValue[numArrayVals];
|
||||||
|
for (int j = 0; j < numArrayVals; j++) {
|
||||||
|
evalues[j] = ElementValue.readElementValue(dis, cpGen.getConstantPool());
|
||||||
|
}
|
||||||
|
return new ArrayElementValueGen(ARRAY, evalues, cpGen);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected element value kind in annotation: " + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void dump(DataOutputStream dos) throws IOException;
|
public abstract void dump(DataOutputStream dos) throws IOException;
|
||||||
|
|
||||||
protected ConstantPoolGen getConstantPool() {
|
protected ConstantPoolGen getConstantPool() {
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ public class EnumElementValueGen extends ElementValueGen {
|
|||||||
super(ENUM_CONSTANT, cpool);
|
super(ENUM_CONSTANT, cpool);
|
||||||
if (copyPoolEntries) {
|
if (copyPoolEntries) {
|
||||||
typeIdx = cpool.addUtf8(value.getEnumTypeString());// was
|
typeIdx = cpool.addUtf8(value.getEnumTypeString());// was
|
||||||
// addClass(value.getEnumTypeString());
|
// addClass(value.getEnumTypeString());
|
||||||
valueIdx = cpool.addUtf8(value.getEnumValueString()); // was
|
valueIdx = cpool.addUtf8(value.getEnumValueString()); // was
|
||||||
// addString(value.getEnumValueString());
|
// addString(value.getEnumValueString());
|
||||||
} else {
|
} else {
|
||||||
typeIdx = value.getTypeIndex();
|
typeIdx = value.getTypeIndex();
|
||||||
valueIdx = value.getValueIndex();
|
valueIdx = value.getValueIndex();
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ package haidnor.jvm.bcel.generic;
|
|||||||
/**
|
/**
|
||||||
* Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite
|
* Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite
|
||||||
* the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted.
|
* the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted.
|
||||||
*
|
* <p>
|
||||||
* The Lava Language Specification specifies exactly which <i>RUN-TIME</i> and which <i>LINKING</i> exceptions each
|
* The Lava Language Specification specifies exactly which <i>RUN-TIME</i> and which <i>LINKING</i> exceptions each
|
||||||
* instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may
|
* instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may
|
||||||
* be possible that an Instruction implementing this interface returns a Class[] of size 0.
|
* be possible that an Instruction implementing this interface returns a Class[] of size 0.
|
||||||
*
|
* <p>
|
||||||
* Please note that we speak of an "exception" here when we mean any "Throwable" object; so this term is equally used
|
* Please note that we speak of an "exception" here when we mean any "Throwable" object; so this term is equally used
|
||||||
* for "Exception" and "Error" objects.
|
* for "Exception" and "Error" objects.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -48,30 +48,14 @@ public class FieldGen extends FieldGenOrMethodGen {
|
|||||||
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
return THIS.getSignature().hashCode() ^ THIS.getName().hashCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @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;
|
private Object value;
|
||||||
|
|
||||||
private List<FieldObserver> observers;
|
private List<FieldObserver> observers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate from existing field.
|
* Instantiate from existing field.
|
||||||
*
|
*
|
||||||
* @param field Field object
|
* @param field Field object
|
||||||
* @param cp constant pool (must contain the same entries as the field's constant pool)
|
* @param cp constant pool (must contain the same entries as the field's constant pool)
|
||||||
*/
|
*/
|
||||||
public FieldGen(final JavaField field, final ConstantPoolGen cp) {
|
public FieldGen(final JavaField field, final ConstantPoolGen cp) {
|
||||||
this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
|
this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp);
|
||||||
@@ -93,9 +77,9 @@ public class FieldGen extends FieldGenOrMethodGen {
|
|||||||
* value associated with it as defined by setInitValue().
|
* value associated with it as defined by setInitValue().
|
||||||
*
|
*
|
||||||
* @param accessFlags access qualifiers
|
* @param accessFlags access qualifiers
|
||||||
* @param type field type
|
* @param type field type
|
||||||
* @param name field name
|
* @param name field name
|
||||||
* @param cp constant pool
|
* @param cp constant pool
|
||||||
*/
|
*/
|
||||||
public FieldGen(final int accessFlags, final Type type, final String name, final ConstantPoolGen cp) {
|
public FieldGen(final int accessFlags, final Type type, final String name, final ConstantPoolGen cp) {
|
||||||
super(accessFlags);
|
super(accessFlags);
|
||||||
@@ -104,28 +88,42 @@ public class FieldGen extends FieldGenOrMethodGen {
|
|||||||
setConstantPool(cp);
|
setConstantPool(cp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 void addAnnotationsAsAttribute(final ConstantPoolGen cp) {
|
private void addAnnotationsAsAttribute(final ConstantPoolGen cp) {
|
||||||
Stream.of(AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries())).forEach(this::addAttribute);
|
Stream.of(AnnotationEntryGen.getAnnotationAttributes(cp, super.getAnnotationEntries())).forEach(this::addAttribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addConstant() {
|
private int addConstant() {
|
||||||
switch (super.getType().getType()) { // sic
|
switch (super.getType().getType()) { // sic
|
||||||
case Const.T_INT:
|
case Const.T_INT:
|
||||||
case Const.T_CHAR:
|
case Const.T_CHAR:
|
||||||
case Const.T_BYTE:
|
case Const.T_BYTE:
|
||||||
case Const.T_BOOLEAN:
|
case Const.T_BOOLEAN:
|
||||||
case Const.T_SHORT:
|
case Const.T_SHORT:
|
||||||
return super.getConstantPool().addInteger(((Integer) value).intValue());
|
return super.getConstantPool().addInteger(((Integer) value).intValue());
|
||||||
case Const.T_FLOAT:
|
case Const.T_FLOAT:
|
||||||
return super.getConstantPool().addFloat(((Float) value).floatValue());
|
return super.getConstantPool().addFloat(((Float) value).floatValue());
|
||||||
case Const.T_DOUBLE:
|
case Const.T_DOUBLE:
|
||||||
return super.getConstantPool().addDouble(((Double) value).doubleValue());
|
return super.getConstantPool().addDouble(((Double) value).doubleValue());
|
||||||
case Const.T_LONG:
|
case Const.T_LONG:
|
||||||
return super.getConstantPool().addLong(((Long) value).longValue());
|
return super.getConstantPool().addLong(((Long) value).longValue());
|
||||||
case Const.T_REFERENCE:
|
case Const.T_REFERENCE:
|
||||||
return super.getConstantPool().addString((String) value);
|
return super.getConstantPool().addString((String) value);
|
||||||
default:
|
default:
|
||||||
throw new IllegalStateException("Unhandled : " + super.getType().getType()); // sic
|
throw new IllegalStateException("Unhandled : " + super.getType().getType()); // sic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,31 +200,6 @@ public class FieldGen extends FieldGenOrMethodGen {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSignature() {
|
|
||||||
return super.getType().getSignature();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
|
|
||||||
* signature.
|
|
||||||
*
|
|
||||||
* @see Object#hashCode()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return bcelComparator.hashCode(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove observer for this object.
|
|
||||||
*/
|
|
||||||
public void removeObserver(final FieldObserver o) {
|
|
||||||
if (observers != null) {
|
|
||||||
observers.remove(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInitValue(final boolean b) {
|
public void setInitValue(final boolean b) {
|
||||||
checkType(Type.BOOLEAN);
|
checkType(Type.BOOLEAN);
|
||||||
if (b) {
|
if (b) {
|
||||||
@@ -293,6 +266,31 @@ public class FieldGen extends FieldGenOrMethodGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSignature() {
|
||||||
|
return super.getType().getSignature();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR
|
||||||
|
* signature.
|
||||||
|
*
|
||||||
|
* @see Object#hashCode()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return bcelComparator.hashCode(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove observer for this object.
|
||||||
|
*/
|
||||||
|
public void removeObserver(final FieldObserver o) {
|
||||||
|
if (observers != null) {
|
||||||
|
observers.remove(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setValue(final int index) {
|
private void setValue(final int index) {
|
||||||
final ConstantPool cp = super.getConstantPool().getConstantPool();
|
final ConstantPool cp = super.getConstantPool().getConstantPool();
|
||||||
final Constant c = cp.getConstant(index);
|
final Constant c = cp.getConstant(index);
|
||||||
|
|||||||
@@ -29,29 +29,25 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
|
public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable {
|
||||||
|
|
||||||
|
private final List<Attribute> attributeList = new ArrayList<>();
|
||||||
|
// @since 6.0
|
||||||
|
private final List<AnnotationEntryGen> annotationList = new ArrayList<>();
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected String name;
|
protected String name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected Type type;
|
protected Type type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
* @deprecated (since 6.0) will be made private; do not access directly, use getter/setter
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected ConstantPoolGen cp;
|
protected ConstantPoolGen cp;
|
||||||
|
|
||||||
private final List<Attribute> attributeList = new ArrayList<>();
|
|
||||||
|
|
||||||
// @since 6.0
|
|
||||||
private final List<AnnotationEntryGen> annotationList = new ArrayList<>();
|
|
||||||
|
|
||||||
protected FieldGenOrMethodGen() {
|
protected FieldGenOrMethodGen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +103,10 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
|||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setConstantPool(final ConstantPoolGen cp) { // TODO could be package-protected?
|
||||||
|
this.cp = cp;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return name of method/field.
|
* @return name of method/field.
|
||||||
*/
|
*/
|
||||||
@@ -115,6 +115,11 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(final String name) { // TODO could be package-protected?
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return signature of method/field.
|
* @return signature of method/field.
|
||||||
*/
|
*/
|
||||||
@@ -125,6 +130,14 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setType(final Type type) { // TODO could be package-protected?
|
||||||
|
if (type.getType() == Const.T_ADDRESS) {
|
||||||
|
throw new IllegalArgumentException("Type can not be " + type);
|
||||||
|
}
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 6.0
|
* @since 6.0
|
||||||
*/
|
*/
|
||||||
@@ -152,21 +165,4 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn
|
|||||||
public void removeAttributes() {
|
public void removeAttributes() {
|
||||||
attributeList.clear();
|
attributeList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConstantPool(final ConstantPoolGen cp) { // TODO could be package-protected?
|
|
||||||
this.cp = cp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setName(final String name) { // TODO could be package-protected?
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setType(final Type type) { // TODO could be package-protected?
|
|
||||||
if (type.getType() == Const.T_ADDRESS) {
|
|
||||||
throw new IllegalArgumentException("Type can not be " + type);
|
|
||||||
}
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,10 +43,9 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
|
|||||||
/**
|
/**
|
||||||
* @return name of the referenced class/interface
|
* @return name of the referenced class/interface
|
||||||
* @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code
|
* @deprecated If the instruction references an array class, this method will return "java.lang.Object". For code
|
||||||
* generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an
|
* generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an
|
||||||
* array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
|
* array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly
|
||||||
* distinguishes between class types and array types.
|
* distinguishes between class types and array types.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public String getClassName(final ConstantPoolGen cpg) {
|
public String getClassName(final ConstantPoolGen cpg) {
|
||||||
@@ -63,7 +62,7 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
|
|||||||
/**
|
/**
|
||||||
* @return type of the referenced class/interface
|
* @return type of the referenced class/interface
|
||||||
* @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use
|
* @deprecated If the instruction references an array class, the ObjectType returned will be invalid. Use
|
||||||
* getReferenceType() instead.
|
* getReferenceType() instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ObjectType getClassType(final ConstantPoolGen cpg) {
|
public ObjectType getClassType(final ConstantPoolGen cpg) {
|
||||||
@@ -100,7 +99,7 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass {
|
|||||||
*
|
*
|
||||||
* @param cpg the ConstantPoolGen used to create the instruction
|
* @param cpg the ConstantPoolGen used to create the instruction
|
||||||
* @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced
|
* @return an ObjectType (if the referenced class type is a class or interface), or an ArrayType (if the referenced
|
||||||
* class type is an array class)
|
* class type is an array class)
|
||||||
*/
|
*/
|
||||||
public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
|
public ReferenceType getReferenceType(final ConstantPoolGen cpg) {
|
||||||
final ConstantPool cp = cpg.getConstantPool();
|
final ConstantPool cp = cpg.getConstantPool();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import haidnor.jvm.bcel.ExceptionConst;
|
|||||||
* <PRE>
|
* <PRE>
|
||||||
* Stack: ..., objectref -> ..., value
|
* Stack: ..., objectref -> ..., value
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*
|
* <p>
|
||||||
* OR
|
* OR
|
||||||
*
|
*
|
||||||
* <PRE>
|
* <PRE>
|
||||||
@@ -66,7 +66,7 @@ public class GETFIELD extends FieldInstruction implements ExceptionThrower, Stac
|
|||||||
@Override
|
@Override
|
||||||
public Class<?>[] getExceptions() {
|
public Class<?>[] getExceptions() {
|
||||||
return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION,
|
return ExceptionConst.createExceptions(ExceptionConst.EXCS.EXCS_FIELD_AND_METHOD_RESOLUTION, ExceptionConst.NULL_POINTER_EXCEPTION,
|
||||||
ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR);
|
ExceptionConst.INCOMPATIBLE_CLASS_CHANGE_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user