diff --git a/pom.xml b/pom.xml
index ce2f133839..7b2820c28d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -184,6 +184,11 @@
Sam Yoon
+
+
+ Hippo
+ hippah at protonmail.com
+
diff --git a/src/main/java/org/apache/bcel/classfile/Attribute.java b/src/main/java/org/apache/bcel/classfile/Attribute.java
index 185360e60d..0b7b6bd8b8 100644
--- a/src/main/java/org/apache/bcel/classfile/Attribute.java
+++ b/src/main/java/org/apache/bcel/classfile/Attribute.java
@@ -93,6 +93,7 @@ protected static void println(final String msg) {
}
}
+
/**
* 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
@@ -110,6 +111,28 @@ protected static void println(final String msg) {
*/
public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool)
throws IOException, ClassFormatException
+ {
+ return readAttribute(file, constant_pool, false);
+ }
+
+ /**
+ * Class method reads one attribute from the input data stream. This method
+ * must not be accessible from the outside. It is called by the Field and
+ * Method constructor methods.
+ *
+ * @see Field
+ * @see Method
+ *
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @param isOak If the the class file is oak
+ * @return Attribute
+ * @throws IOException
+ * @throws ClassFormatException
+ * @since 6.0
+ */
+ public static Attribute readAttribute(final DataInput file, final ConstantPool constant_pool, final boolean isOak)
+ throws IOException, ClassFormatException
{
byte tag = Const.ATTR_UNKNOWN; // Unknown attribute
// Get class name from constant pool via `name_index' indirection
@@ -145,7 +168,7 @@ public static Attribute readAttribute(final DataInput file, final ConstantPool c
case Const.ATTR_SOURCE_FILE:
return new SourceFile(name_index, length, file, constant_pool);
case Const.ATTR_CODE:
- return new Code(name_index, length, file, constant_pool);
+ return new Code(name_index, length, file, constant_pool, isOak);
case Const.ATTR_EXCEPTIONS:
return new ExceptionTable(name_index, length, file, constant_pool);
case Const.ATTR_LINE_NUMBER_TABLE:
diff --git a/src/main/java/org/apache/bcel/classfile/ClassParser.java b/src/main/java/org/apache/bcel/classfile/ClassParser.java
index a592bfed06..79a3b29174 100644
--- a/src/main/java/org/apache/bcel/classfile/ClassParser.java
+++ b/src/main/java/org/apache/bcel/classfile/ClassParser.java
@@ -58,6 +58,7 @@ public final class ClassParser {
private Attribute[] attributes; // attributes defined in the class
private final boolean isZip; // Loaded from zip file
private static final int BUFSIZE = 8192;
+ private boolean isOak; // Is oak class file
/**
@@ -290,7 +291,7 @@ private void readMethods() throws IOException, ClassFormatException {
final int methods_count = dataInputStream.readUnsignedShort();
methods = new Method[methods_count];
for (int i = 0; i < methods_count; i++) {
- methods[i] = new Method(dataInputStream, constantPool);
+ methods[i] = new Method(dataInputStream, constantPool, isOak);
}
}
@@ -303,5 +304,6 @@ private void readMethods() throws IOException, ClassFormatException {
private void readVersion() throws IOException, ClassFormatException {
minor = dataInputStream.readUnsignedShort();
major = dataInputStream.readUnsignedShort();
+ isOak = major < Const.MAJOR_1_1 || (major == Const.MAJOR_1_1 && minor < 3);
}
}
diff --git a/src/main/java/org/apache/bcel/classfile/Code.java b/src/main/java/org/apache/bcel/classfile/Code.java
index cedc53527e..6a1e06b8a2 100644
--- a/src/main/java/org/apache/bcel/classfile/Code.java
+++ b/src/main/java/org/apache/bcel/classfile/Code.java
@@ -48,6 +48,7 @@ public final class Code extends Attribute {
private byte[] code; // Actual byte code
private CodeException[] exceptionTable; // Table of handled exceptions
private Attribute[] attributes; // or LocalVariable
+ private boolean isOak; // If the class file follows oak format
/**
@@ -60,6 +61,7 @@ public Code(final Code c) {
}
+
/**
* @param name_index Index pointing to the name Code
* @param length Content length in bytes
@@ -68,10 +70,23 @@ public Code(final Code c) {
*/
Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool)
throws IOException {
+ this(name_index, length, file, constant_pool, false);
+ }
+
+ /**
+ * @param name_index Index pointing to the name Code
+ * @param length Content length in bytes
+ * @param file Input stream
+ * @param constant_pool Array of constants
+ * @param isOak If the class file is oak
+ */
+ Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool, final boolean isOak)
+ throws IOException {
// Initialize with some default values which will be overwritten later
- this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null,
- (CodeException[]) null, (Attribute[]) null, constant_pool);
- final int code_length = file.readInt();
+ this(name_index, length, isOak ? file.readUnsignedByte() : file.readUnsignedShort(), isOak ? file.readUnsignedByte() : file.readUnsignedShort(),
+ (byte[]) null, (CodeException[]) null, (Attribute[]) null, constant_pool);
+ this.isOak = isOak;
+ final int code_length = isOak ? file.readUnsignedShort() : file.readInt();
code = new byte[code_length]; // Read byte code
file.readFully(code);
/* Read exception table that contains all regions where an exception
@@ -109,13 +124,30 @@ public Code(final Code c) {
* @param constant_pool Array of constants
*/
public Code(final int name_index, final int length, final int maxStack, final int maxLocals, final byte[] code,
- final CodeException[] exceptionTable, final Attribute[] attributes, final ConstantPool constant_pool) {
+ final CodeException[] exceptionTable, final Attribute[] attributes, final ConstantPool constant_pool) {
+ this(name_index, length, maxStack, maxLocals, code, exceptionTable, attributes, constant_pool, false);
+ }
+
+ /**
+ * @param name_index Index pointing to the name Code
+ * @param length Content length in bytes
+ * @param maxStack Maximum size of stack
+ * @param maxLocals Number of local variables
+ * @param code Actual byte code
+ * @param exceptionTable of handled exceptions
+ * @param attributes Attributes of code: LineNumber or LocalVariable
+ * @param constant_pool Array of constants
+ * @param isOak If the class file follows the oak format
+ */
+ public Code(final int name_index, final int length, final int maxStack, final int maxLocals, final byte[] code,
+ final CodeException[] exceptionTable, final Attribute[] attributes, final ConstantPool constant_pool, final boolean isOak) {
super(Const.ATTR_CODE, name_index, length, constant_pool);
this.maxStack = maxStack;
this.maxLocals = maxLocals;
this.code = code != null ? code : ArrayUtils.EMPTY_BYTE_ARRAY;
this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY;
this.attributes = attributes != null ? attributes : EMPTY_ATTRIBUTE_ARRAY;
+ this.isOak = isOak;
super.setLength(calculateLength()); // Adjust length
}
@@ -142,9 +174,15 @@ public void accept( final Visitor v ) {
@Override
public void dump( final DataOutputStream file ) throws IOException {
super.dump(file);
- file.writeShort(maxStack);
- file.writeShort(maxLocals);
- file.writeInt(code.length);
+ if (isOak) {
+ file.writeByte(maxStack);
+ file.writeByte(maxLocals);
+ file.writeShort(code.length);
+ } else {
+ file.writeShort(maxStack);
+ file.writeShort(maxLocals);
+ file.writeInt(code.length);
+ }
file.write(code, 0, code.length);
file.writeShort(exceptionTable.length);
for (final CodeException exception : exceptionTable) {
@@ -230,7 +268,19 @@ public int getMaxStack() {
* and excluding all its attributes
*/
private int getInternalLength() {
- return 2 /*maxStack*/+ 2 /*maxLocals*/+ 4 /*code length*/
+ final int maxStack;
+ final int maxLocals;
+ final int codeLength;
+ if (isOak) {
+ maxStack = 1;
+ maxLocals = 1;
+ codeLength = 2;
+ } else {
+ maxStack = 2;
+ maxLocals = 2;
+ codeLength = 4;
+ }
+ return maxStack + maxLocals + codeLength
+ code.length /*byte-code*/
+ 2 /*exception-table length*/
+ 8 * (exceptionTable == null ? 0 : exceptionTable.length) /* exception table */
diff --git a/src/main/java/org/apache/bcel/classfile/FieldOrMethod.java b/src/main/java/org/apache/bcel/classfile/FieldOrMethod.java
index 6b70942185..8ed8e82d67 100644
--- a/src/main/java/org/apache/bcel/classfile/FieldOrMethod.java
+++ b/src/main/java/org/apache/bcel/classfile/FieldOrMethod.java
@@ -100,12 +100,23 @@ protected FieldOrMethod(final DataInputStream file, final ConstantPool constant_
* @throws ClassFormatException
*/
protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool) throws IOException, ClassFormatException {
+ this(file, constant_pool, false);
+ }
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @param isOak If the class file is oak
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ protected FieldOrMethod(final DataInput file, final ConstantPool constant_pool, final boolean isOak) throws IOException, ClassFormatException {
this(file.readUnsignedShort(), file.readUnsignedShort(), file.readUnsignedShort(), null,
constant_pool);
final int attributes_count = file.readUnsignedShort();
attributes = new Attribute[attributes_count];
for (int i = 0; i < attributes_count; i++) {
- attributes[i] = Attribute.readAttribute(file, constant_pool);
+ attributes[i] = Attribute.readAttribute(file, constant_pool, isOak);
}
this.attributes_count = attributes_count; // init deprecated field
}
diff --git a/src/main/java/org/apache/bcel/classfile/Method.java b/src/main/java/org/apache/bcel/classfile/Method.java
index a414de7a49..ebbe539753 100644
--- a/src/main/java/org/apache/bcel/classfile/Method.java
+++ b/src/main/java/org/apache/bcel/classfile/Method.java
@@ -84,7 +84,19 @@ public Method(final Method c) {
*/
Method(final DataInput file, final ConstantPool constant_pool) throws IOException,
ClassFormatException {
- super(file, constant_pool);
+ this(file, constant_pool, false);
+ }
+
+ /**
+ * Construct object from file stream.
+ * @param file Input stream
+ * @param isOak If the class file is oak
+ * @throws IOException
+ * @throws ClassFormatException
+ */
+ Method(final DataInput file, final ConstantPool constant_pool, final boolean isOak) throws IOException,
+ ClassFormatException {
+ super(file, constant_pool, isOak);
}