|
|
|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package com.sun.org.apache.bcel.internal.classfile; |
|
|
|
import java.io.DataInput; |
|
import java.io.DataOutputStream; |
|
import java.io.IOException; |
|
|
|
import com.sun.org.apache.bcel.internal.Const; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final class Code extends Attribute { |
|
|
|
private int max_stack; |
|
private int max_locals; |
|
private byte[] code; |
|
private CodeException[] exception_table; |
|
private Attribute[] attributes; |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Code(final Code c) { |
|
this(c.getNameIndex(), c.getLength(), c.getMaxStack(), c.getMaxLocals(), c.getCode(), c |
|
.getExceptionTable(), c.getAttributes(), c.getConstantPool()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Code(final int name_index, final int length, final DataInput file, final ConstantPool constant_pool) |
|
throws IOException { |
|
|
|
this(name_index, length, file.readUnsignedShort(), file.readUnsignedShort(), (byte[]) null, |
|
(CodeException[]) null, (Attribute[]) null, constant_pool); |
|
final int code_length = file.readInt(); |
|
code = new byte[code_length]; |
|
file.readFully(code); |
|
|
|
|
|
*/ |
|
final int exception_table_length = file.readUnsignedShort(); |
|
exception_table = new CodeException[exception_table_length]; |
|
for (int i = 0; i < exception_table_length; i++) { |
|
exception_table[i] = new CodeException(file); |
|
} |
|
|
|
|
|
*/ |
|
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); |
|
} |
|
|
|
|
|
|
|
*/ |
|
super.setLength(length); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Code(final int name_index, final int length, final int max_stack, final int max_locals, final byte[] code, |
|
final CodeException[] exception_table, final Attribute[] attributes, final ConstantPool constant_pool) { |
|
super(Const.ATTR_CODE, name_index, length, constant_pool); |
|
this.max_stack = max_stack; |
|
this.max_locals = max_locals; |
|
this.code = code != null ? code : new byte[0]; |
|
this.exception_table = exception_table != null ? exception_table : new CodeException[0]; |
|
this.attributes = attributes != null ? attributes : new Attribute[0]; |
|
super.setLength(calculateLength()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public void accept( final Visitor v ) { |
|
v.visitCode(this); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public final void dump( final DataOutputStream file ) throws IOException { |
|
super.dump(file); |
|
file.writeShort(max_stack); |
|
file.writeShort(max_locals); |
|
file.writeInt(code.length); |
|
file.write(code, 0, code.length); |
|
file.writeShort(exception_table.length); |
|
for (final CodeException exception : exception_table) { |
|
exception.dump(file); |
|
} |
|
file.writeShort(attributes.length); |
|
for (final Attribute attribute : attributes) { |
|
attribute.dump(file); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final Attribute[] getAttributes() { |
|
return attributes; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public LineNumberTable getLineNumberTable() { |
|
for (final Attribute attribute : attributes) { |
|
if (attribute instanceof LineNumberTable) { |
|
return (LineNumberTable) attribute; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public LocalVariableTable getLocalVariableTable() { |
|
for (final Attribute attribute : attributes) { |
|
if (attribute instanceof LocalVariableTable) { |
|
return (LocalVariableTable) attribute; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final byte[] getCode() { |
|
return code; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final CodeException[] getExceptionTable() { |
|
return exception_table; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final int getMaxLocals() { |
|
return max_locals; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final int getMaxStack() { |
|
return max_stack; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private int getInternalLength() { |
|
return 2 + 2 + 4 |
|
+ code.length |
|
+ 2 |
|
+ 8 * (exception_table == null ? 0 : exception_table.length) |
|
+ 2 /* attributes count */; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private int calculateLength() { |
|
int len = 0; |
|
if (attributes != null) { |
|
for (final Attribute attribute : attributes) { |
|
len += attribute.getLength() + 6 /*attribute header size*/; |
|
} |
|
} |
|
return len + getInternalLength(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setAttributes( final Attribute[] attributes ) { |
|
this.attributes = attributes != null ? attributes : new Attribute[0]; |
|
super.setLength(calculateLength()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setCode( final byte[] code ) { |
|
this.code = code != null ? code : new byte[0]; |
|
super.setLength(calculateLength()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setExceptionTable( final CodeException[] exception_table ) { |
|
this.exception_table = exception_table != null ? exception_table : new CodeException[0]; |
|
super.setLength(calculateLength()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setMaxLocals( final int max_locals ) { |
|
this.max_locals = max_locals; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final void setMaxStack( final int max_stack ) { |
|
this.max_stack = max_stack; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public final String toString( final boolean verbose ) { |
|
final StringBuilder buf = new StringBuilder(100); |
|
buf.append("Code(max_stack = ").append(max_stack).append(", max_locals = ").append( |
|
max_locals).append(", code_length = ").append(code.length).append(")\n").append( |
|
Utility.codeToString(code, super.getConstantPool(), 0, -1, verbose)); |
|
if (exception_table.length > 0) { |
|
buf.append("\nException handler(s) = \n").append("From\tTo\tHandler\tType\n"); |
|
for (final CodeException exception : exception_table) { |
|
buf.append(exception.toString(super.getConstantPool(), verbose)).append("\n"); |
|
} |
|
} |
|
if (attributes.length > 0) { |
|
buf.append("\nAttribute(s) = "); |
|
for (final Attribute attribute : attributes) { |
|
buf.append("\n").append(attribute); |
|
} |
|
} |
|
return buf.toString(); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public final String toString() { |
|
return toString(true); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@Override |
|
public Attribute copy( final ConstantPool _constant_pool ) { |
|
final Code c = (Code) clone(); |
|
if (code != null) { |
|
c.code = new byte[code.length]; |
|
System.arraycopy(code, 0, c.code, 0, code.length); |
|
} |
|
c.setConstantPool(_constant_pool); |
|
c.exception_table = new CodeException[exception_table.length]; |
|
for (int i = 0; i < exception_table.length; i++) { |
|
c.exception_table[i] = exception_table[i].copy(); |
|
} |
|
c.attributes = new Attribute[attributes.length]; |
|
for (int i = 0; i < attributes.length; i++) { |
|
c.attributes[i] = attributes[i].copy(_constant_pool); |
|
} |
|
return c; |
|
} |
|
} |