CODETOOLS-7902524 Asmtools support: JEP 359 Records(Preview)

CODETOOLS-7902527 jasm has defects while writing ConstantPool/MethodParamethers structs
This commit is contained in:
lkuskov 2019-11-06 11:30:00 -08:00
parent e4fd04e0af
commit 187e90eb4a
33 changed files with 866 additions and 451 deletions

@ -40,6 +40,10 @@ class AttrData implements Data {
attrNameCPX = cdata.pool.FindCellAsciz(name);
}
protected ClassData getClassData() {
return clsData;
}
// full length of the attribute
// declared in Data
public int getLength() {

@ -37,10 +37,6 @@ import static org.openjdk.asmtools.jasm.Tables.*;
*/
class ClassData extends MemberData {
/*-------------------------------------------------------- */
/* ClassData inner classes */
/*-------------------------------------------------------- */
/* ClassData Fields */
CFVersion cfv;
ConstantPool.ConstCell me, father;
@ -51,24 +47,23 @@ class ClassData extends MemberData {
ArrayList<MethodData> methods = new ArrayList<>();
DataVectorAttr<InnerClassData> innerClasses = null;
DataVectorAttr<BootstrapMethodData> bootstrapMethodsAttr = null;
// JEP 181 - NestHost, NestMembers attributes since class version 55.0
CPXAttr nestHostAttr;
NestMembersAttr nestMembersAttr;
// JEP 359 - Record attribute since class file 58.65535
private RecordData recordData;
ModuleAttr moduleAttribute = null;
Environment env;
protected ConstantPool pool;
private static final String DEFAULT_EXTENSION = ".class";
String fileExtension = DEFAULT_EXTENSION;
public CDOutputStream cdos;
/*-------------------------------------------------------- */
/**
* init
*
* Initializes the ClassData.
*
* @param me The constant pool reference to this class
@ -119,10 +114,7 @@ class ClassData extends MemberData {
cdos = new CDOutputStream();
}
/* *********************************************** */
/**
* isInterface
*
* Predicate that describes if this class has an access flag indicating that it is an
* interface.
*
@ -188,7 +180,17 @@ class ClassData extends MemberData {
}
}
/*-------------------------------------------------------- API */
// API
// Record
public RecordData setRecord(int where) {
if( recordAttributeExists() ) {
env.error(where, "warn.record.repeated");
}
this.recordData = new RecordData(cls);
return this.recordData;
}
// Field
public ConstantPool.ConstValue_Pair mkNape(ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
return new ConstantPool.ConstValue_Pair(ConstType.CONSTANT_NAMEANDTYPE, name, sig);
}
@ -197,7 +199,24 @@ class ClassData extends MemberData {
return mkNape(pool.FindCellAsciz(name), pool.FindCellAsciz(sig));
}
public void setSourceFileName(String name) {
public FieldData addFieldIfAbsent(int access, ConstantPool.ConstCell name, ConstantPool.ConstCell sig) {
ConstantPool.ConstValue_Pair nape = mkNape(name, sig);
env.traceln(" [ClassData.addFieldIfAbsent]: #" + nape.left.arg + ":#" + nape.right.arg);
FieldData fd = getField(nape);
if( fd == null ) {
env.traceln(" [ClassData.addFieldIfAbsent]: new field.");
fd = addField(access,nape);
}
return fd;
}
private FieldData getField(ConstantPool.ConstValue_Pair nape) {
for (FieldData fd : fields) {
if( fd.getNameDesc().equals(nape) ) {
return fd;
}
}
return null;
}
public FieldData addField(int access, ConstantPool.ConstValue_Pair nape) {
@ -216,7 +235,7 @@ class ClassData extends MemberData {
}
public ConstantPool.ConstCell LocalFieldRef(FieldData field) {
return pool.FindCell(ConstType.CONSTANT_FIELD, me, pool.FindCell(field.nape));
return pool.FindCell(ConstType.CONSTANT_FIELD, me, pool.FindCell(field.getNameDesc()));
}
public ConstantPool.ConstCell LocalFieldRef(ConstantPool.ConstValue nape) {
@ -340,7 +359,6 @@ class ClassData extends MemberData {
}
/*====================================================== write */
public void write(CheckedDataOutputStream out) throws IOException {
// Write the header
@ -383,9 +401,14 @@ class ClassData extends MemberData {
out.writeShort(0);
}
DataVector attrs = new DataVector();
// Write the attributes
DataVector attrs = getAttrVector();
attrs.write(out);
} // end ClassData.write()
@Override
protected DataVector getAttrVector() {
DataVector attrs = new DataVector();
if( moduleAttribute != null ) {
if (annotAttrVis != null)
attrs.add(annotAttrVis);
@ -394,6 +417,10 @@ class ClassData extends MemberData {
attrs.add(moduleAttribute);
} else {
attrs.add(sourceFileNameAttr);
// JEP 359 since class file 58.65535
if( recordData != null ) {
attrs.add(recordData);
}
if (innerClasses != null)
attrs.add(innerClasses);
if (syntheticAttr != null)
@ -411,18 +438,18 @@ class ClassData extends MemberData {
if (bootstrapMethodsAttr != null)
attrs.add(bootstrapMethodsAttr);
// since class version 55.0
if(nestHostExists())
if(nestHostAttributeExists())
attrs.add(nestHostAttr);
if(nestMembersExist())
attrs.add(nestMembersAttr);
if(nestMembersAttributesExist())
attrs.add(nestMembersAttr);
}
attrs.write(out);
} // end ClassData.write()
return attrs;
}
static char fileSeparator; //=System.getProperty("file.separator");
/**
* write to the directory passed with -d option
* Writes to the directory passed with -d option
*/
public void write(File destdir) throws IOException {
File outfile;
@ -463,17 +490,15 @@ class ClassData extends MemberData {
cdos.setLimit(bytelimit);
}
public boolean nestHostExists() {
public boolean nestHostAttributeExists() {
return nestHostAttr != null;
}
public boolean nestMembersExist() {
return nestMembersAttr != null;
}
public boolean nestMembersAttributesExist() { return nestMembersAttr != null; }
public boolean recordAttributeExists() { return recordData != null; }
/**
* CDOutputStream
*
* This is a wrapper for DataOutputStream, used for debugging purposes. it allows
* writing the byte-stream of a class up to a given byte number.
*/
@ -590,14 +615,6 @@ class ClassData extends MemberData {
dos.writeUTF(s);
check("Writing writeUTF: " + s);
}
/*
public int writeUTF(String str, DataOutput out) throws IOException{
int ret = dos.writeUTF(str, out);
check("Writing writeUTF: " + str);
return ret;
}
* */
}
}// end class ClassData

@ -23,8 +23,12 @@
package org.openjdk.asmtools.jasm;
import org.openjdk.asmtools.jasm.Tables.ConstType;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
/**
* ConstantPool
@ -345,7 +349,13 @@ public class ConstantPool implements Iterable<ConstantPool.ConstCell> {
if (tag != dobj.tag) {
return false;
}
return (dobj.left == left) && (dobj.right == right);
if (dobj.left != null)
if (!dobj.left.equals(left))
return false;
if (dobj.right != null)
if (!dobj.right.equals(right))
return false;
return true;
}
@Override
@ -494,7 +504,11 @@ public class ConstantPool implements Iterable<ConstantPool.ConstCell> {
if (obj == null) {
return false;
}
return obj == this;
ConstCell cc = (ConstCell)obj;
if( cc.ref == null ) {
return this.ref == null && cc.rank == this.rank;
}
return cc.ref.equals(this.ref) && cc.rank == this.rank;
}
public boolean isUnset() {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@ package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*
@ -49,7 +50,11 @@ public class DataVector<T extends Data> implements Iterable<T> {
elements.add(element);
}
// full length of the attribute
public void addAll(List<T> collection) {
elements.addAll(collection);
}
// full length of the attribute conveyor
// declared in Data
public int getLength() {
int length = 0;

@ -36,23 +36,23 @@ class DataVectorAttr<T extends Data> extends AttrData implements Iterable<T> {
private ArrayList<T> elements;
private boolean byteIndex;
public DataVectorAttr(ClassData cls, String name, boolean byteIndex, ArrayList<T> initialData) {
private DataVectorAttr(ClassData cls, String name, boolean byteIndex, ArrayList<T> initialData) {
super(cls, name);
this.elements = initialData;
this.byteIndex = byteIndex;
}
public DataVectorAttr(ClassData cls, String name, ArrayList<T> initialData) {
DataVectorAttr(ClassData cls, String name, ArrayList<T> initialData) {
this(cls, name, false, initialData);
}
public DataVectorAttr(ClassData cls, String name) {
this(cls, name, false, new ArrayList<T>());
DataVectorAttr(ClassData cls, String name) {
this(cls, name, false, new ArrayList<>());
}
public DataVectorAttr(ClassData cls, String name, boolean byteIndex) {
this(cls, name, byteIndex, new ArrayList<T>());
DataVectorAttr(ClassData cls, String name, boolean byteIndex) {
this(cls, name, byteIndex, new ArrayList<>());
}
@ -64,8 +64,8 @@ class DataVectorAttr<T extends Data> extends AttrData implements Iterable<T> {
elements.add(element);
}
public void add(int i, T element) {
elements.add(i, element);
public void put(int i, T element) {
elements.set(i, element);
}
public int size() {

@ -284,11 +284,6 @@ public class Environment {
}
/**
* The filename where the last errors have occurred
*/
String errorFileName;
/**
* List of outstanding error messages
*/
@ -332,7 +327,7 @@ public class Environment {
for (i = off; (i > 0) && (data[i - 1] != '\n') && (data[i - 1] != '\r'); i--);
for (j = off; (j < data.length) && (data[j] != '\n') && (data[j] != '\r'); j++);
String prefix = errorFileName + ":" + ln + ":";
String prefix = simpleInputFileName + ":" + ln + ":";
outputln(prefix + " " + msg.message);
outputln(new String(data, i, j - i));
@ -351,13 +346,11 @@ public class Environment {
* This should be used instead of print.
*/
public void output(String msg) {
// try {
int len = msg.length();
for (int i = 0; i < len; i++) {
out.write(msg.charAt(i));
}
// } catch (IOException e) {
// }
out.flush();
}
/**
@ -365,8 +358,7 @@ public class Environment {
* This should be used instead of println.
*/
public void outputln(String msg) {
output(msg);
out.write('\n');
output((msg == null ? "" : msg) + "\n");
}
/**

@ -24,17 +24,17 @@ package org.openjdk.asmtools.jasm;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
class FieldData extends MemberData {
/*-------------------------------------------------------- */
/* FieldData Fields */
protected ConstantPool.ConstValue_Pair nape;
private ConstantPool.ConstValue_Pair nape;
private AttrData initValue;
/*-------------------------------------------------------- */
public FieldData(ClassData cls, int acc, ConstantPool.ConstValue_Pair nape) {
super(cls, acc);
@ -44,38 +44,36 @@ class FieldData extends MemberData {
}
}
public ConstantPool.ConstValue_Pair getNameDesc() {
return nape;
}
public void SetValue(Argument value_cpx) {
initValue = new CPXAttr(cls, AttrTag.ATT_ConstantValue.parsekey(),
value_cpx);
}
@Override
protected DataVector getAttrVector() {
return getDataVector( new ArrayList<>(){{
if (initValue != null) {
add(initValue);
};
if (syntheticAttr != null) {
add(syntheticAttr);
}
if (deprecatedAttr != null) {
add(deprecatedAttr);
}
}} );
}
public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
out.writeShort(access);
out.writeShort(nape.left.arg);
out.writeShort(nape.right.arg);
DataVector attrs = new DataVector();
if (initValue != null) {
attrs.add(initValue);
}
if (syntheticAttr != null) {
attrs.add(syntheticAttr);
}
if (deprecatedAttr != null) {
attrs.add(deprecatedAttr);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
DataVector attrs = getAttrVector();
attrs.write(out);
}
} // end FieldData

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -310,6 +310,8 @@ public class JasmTokens {
BOOTSTRAPMETHOD (172, "BOOTSTRAPMETHOD", "BootstrapMethod", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
NESTHOST (173, "NESTHOST", "NestHost", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
NESTMEMBERS (174, "NESTMEMBERS", "NestMembers", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
//
RECORD (175, "RECORD", "Record", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
//Module statements
REQUIRES (180, "REQUIRES", "requires", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),

@ -26,16 +26,16 @@ import static org.openjdk.asmtools.jasm.RuntimeConstants.DEPRECATED_ATTRIBUTE;
import static org.openjdk.asmtools.jasm.RuntimeConstants.SYNTHETIC_ATTRIBUTE;
import org.openjdk.asmtools.jasm.Tables.AttrTag;
import java.util.ArrayList;
import java.util.List;
/**
*
*
*/
public class MemberData {
abstract public class MemberData {
protected int access;
protected AttrData syntheticAttr,
deprecatedAttr;
protected AttrData syntheticAttr, deprecatedAttr;
protected DataVectorAttr<AnnotationData> annotAttrVis = null;
protected DataVectorAttr<AnnotationData> annotAttrInv = null;
protected DataVectorAttr<TypeAnnotationData> type_annotAttrVis = null;
@ -47,6 +47,10 @@ public class MemberData {
init(access);
}
public MemberData(ClassData cls) {
this.cls = cls;
}
public void init(int access) {
this.access = access;
}
@ -69,6 +73,28 @@ public class MemberData {
}
}
protected abstract DataVector getAttrVector();
protected final DataVector getDataVector(List<Data> extraAttrs) {
DataVector attrs = new DataVector();
if (extraAttrs != null) {
attrs.addAll(extraAttrs);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
return attrs;
}
public void addAnnotations(ArrayList<AnnotationData> annttns) {
for (AnnotationData annot : annttns) {
boolean invisible = annot.invisible;

@ -59,19 +59,12 @@ class MethodData extends MemberData {
nm = name.arg;
ac = access;
}
// short acc = (short) ac;
// env.traceln("ParamNameData.write() (name[" + nm + "], Flags: (" + access + "). [TESTING: short_access=" + acc + "]");
out.writeShort(nm);
out.writeShort(ac);
}
}// end class MethodParamData
/*-------------------------------------------------------- */
/* MethodParamData Inner Classes */
/**
* DataPArrayAttr
*
* Used to store Parameter Arrays (as attributes)
*/
static public class DataPArrayAttr<T extends Data> extends AttrData implements Constants {
@ -105,7 +98,7 @@ class MethodData extends MemberData {
@Override
public int attrLength() {
int length = 1; // One byte for the paramater count
int length = 1; // One byte for the parameter count
// calculate overall size here rather than in add()
// because it may not be available at the time of invoking of add()
@ -144,7 +137,6 @@ class MethodData extends MemberData {
}// end class DataPArrayAttr
/*-------------------------------------------------------- */
/* Method Data Fields */
protected Environment env;
protected ConstCell nameCell, sigCell;
@ -154,8 +146,6 @@ class MethodData extends MemberData {
protected DataPArrayAttr<AnnotationData> pannotAttrVis = null;
protected DataPArrayAttr<AnnotationData> pannotAttrInv = null;
protected DefaultAnnotationAttr defaultAnnot = null;
protected DataVector attrs = new DataVector();
/*-------------------------------------------------------- */
public MethodData(ClassData cls, int acc,
ConstCell name, ConstCell sig, ArrayList<ConstCell> exc_table) {
@ -183,7 +173,7 @@ class MethodData extends MemberData {
paramNames.add(new ParamNameData(0, null));
}
}
paramNames.add(paramNum, new ParamNameData(access, name));
paramNames.put(paramNum, new ParamNameData(access, name));
}
public CodeAttr startCode(int pos, int paramcnt, Argument max_stack, Argument max_locals) {
@ -214,50 +204,46 @@ class MethodData extends MemberData {
}
}
@Override
protected DataVector getAttrVector() {
DataVector dv = getDataVector( new ArrayList<>(){{
if (exceptions != null) {
add(exceptions);
}
if (syntheticAttr != null) {
add(syntheticAttr);
}
if (deprecatedAttr != null) {
add(deprecatedAttr);
}
if (paramNames != null) {
add(paramNames);
}
if (code != null) {
add(code);
}
if (defaultAnnot != null) {
add(defaultAnnot);
}
}});
dv.addAll(
new ArrayList<>() {{
if (pannotAttrVis != null) {
add(pannotAttrVis);
}
if (pannotAttrInv != null) {
add(pannotAttrInv);
}
}});
return dv;
}
/*====================================================== Write */
public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
out.writeShort(access);
out.writeShort(nameCell.arg);
out.writeShort(sigCell.arg);
if (exceptions != null) {
attrs.add(exceptions);
}
if (syntheticAttr != null) {
attrs.add(syntheticAttr);
}
if (deprecatedAttr != null) {
attrs.add(deprecatedAttr);
}
if (paramNames != null) {
attrs.add(paramNames);
}
if (code != null) {
attrs.add(code);
}
if (defaultAnnot != null) {
attrs.add(defaultAnnot);
}
if (annotAttrVis != null) {
attrs.add(annotAttrVis);
}
if (annotAttrInv != null) {
attrs.add(annotAttrInv);
}
if (type_annotAttrVis != null) {
attrs.add(type_annotAttrVis);
}
if (type_annotAttrInv != null) {
attrs.add(type_annotAttrInv);
}
if (pannotAttrVis != null) {
attrs.add(pannotAttrVis);
}
if (pannotAttrInv != null) {
attrs.add(pannotAttrInv);
}
attrs.write(out);
getAttrVector().write(out);
}
} // end MethodData

@ -22,10 +22,12 @@
*/
package org.openjdk.asmtools.jasm;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.openjdk.asmtools.jasm.JasmTokens.Token;
import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
import static org.openjdk.asmtools.jasm.JasmTokens.*;
import static org.openjdk.asmtools.jasm.Tables.CF_Context;
/**
@ -40,20 +42,37 @@ public class Modifiers {
* Modifier masks
*/
public static final int MM_ATTR = SYNTHETIC_ATTRIBUTE | DEPRECATED_ATTRIBUTE;
public static final int MM_ACCESS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED;
public static final int MM_INTRF = MM_ACCESS | ACC_ABSTRACT | ACC_INTERFACE | MM_ATTR | ACC_ANNOTATION;
public static final int MM_CLASS = MM_ACCESS | ACC_FINAL | ACC_SUPER | ACC_ABSTRACT | ACC_ENUM | MM_ATTR | ACC_MODULE ;
public static final int MM_FIELD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM | MM_ATTR ;
public static final int MM_I_METHOD = ACC_ABSTRACT | ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC | ACC_VARARGS | ACC_BRIDGE | ACC_SYNTHETIC ; // interface method
public static final int MM_CLASS = MM_ACCESS | ACC_FINAL | ACC_SUPER | ACC_ABSTRACT | ACC_ENUM |
MM_ATTR | ACC_MODULE ;
public static final int MM_FIELD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_VOLATILE | ACC_TRANSIENT |
ACC_SYNTHETIC | ACC_ENUM |
ACC_MANDATED | // JEP 359 Record
MM_ATTR;
public static final int MM_I_METHOD = ACC_ABSTRACT | ACC_PUBLIC | ACC_PRIVATE | ACC_STATIC | ACC_VARARGS |
ACC_BRIDGE | ACC_SYNTHETIC ; // interface method
public static final int MM_A_METHOD = MM_ACCESS | ACC_ABSTRACT | MM_ATTR;
public static final int MM_N_METHOD = MM_ACCESS | ACC_STRICT | ACC_VARARGS | ACC_SYNTHETIC | MM_ATTR; // <init>
public static final int MM_METHOD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_INNERCLASS = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM | MM_ATTR ; // | ACC_MODULE ;
public static final int MM_REQUIRES = ACC_TRANSITIVE | ACC_STATIC_PHASE | ACC_SYNTHETIC | ACC_MANDATED ;
public static final int MM_EXPORTS = ACC_SYNTHETIC | ACC_MANDATED ;
public static final int MM_N_METHOD = MM_ACCESS | ACC_STRICT | ACC_VARARGS | ACC_SYNTHETIC | MM_ATTR; // <init>
public static final int MM_METHOD = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED | ACC_BRIDGE |
ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC |
ACC_MANDATED | // JEP 359 Record
MM_ATTR ;
public static final int MM_INNERCLASS = MM_ACCESS | ACC_STATIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE |
ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM | MM_ATTR ;
public static final int MM_REQUIRES = ACC_TRANSITIVE | ACC_STATIC_PHASE | ACC_SYNTHETIC | ACC_MANDATED ;
public static final int MM_EXPORTS = ACC_SYNTHETIC | ACC_MANDATED ;
private Modifiers() {
}
@ -230,13 +249,6 @@ public class Modifiers {
return (mod & (flagA | flagB)) == (flagA | flagB);
}
private static String getNames(int bits) {
return RuntimeConstants.ACC_NAMES.entrySet().stream()
.filter(e -> (e.getKey() & bits) != 0 && !e.getValue().isEmpty())
.map(s->s.getValue())
.collect(Collectors.joining(", "));
}
/**
* Check the modifier flags for the class
*
@ -249,8 +261,8 @@ public class Modifiers {
if( isEnum(mod) ) {
env.error(scanner.pos, "warn.invalid.modifier.class.intenum");
} else if ( !validInterface(mod) ) {
String names = getNames(getInvalidModifiers4Interface(mod));
env.error(scanner.pos, "warn.invalid.modifier.int", (names.isEmpty() ? "." : " - " + names));
env.error(scanner.pos, "warn.invalid.modifier.int",
toString(mod & ~MM_INTRF, CF_Context.CTX_CLASS));
}
if (!isAbstract(mod)) {
env.error(scanner.pos, "warn.invalid.modifier.int.abs");
@ -260,8 +272,8 @@ public class Modifiers {
env.error(scanner.pos, "warn.missing.modifier.class");
}
if (! validClass(mod)) {
String names = getNames(getInvalidModifiers4Class(mod));
env.error(scanner.pos, "warn.invalid.modifier.class", (names.isEmpty() ? "." : " - " + names));
env.error(scanner.pos, "warn.invalid.modifier.class",
toString(mod & ~MM_CLASS, CF_Context.CTX_CLASS));
}
if (isAbstract(mod) && Modifiers.isFinal(mod)) {
env.error(scanner.pos, "warn.invalid.modifier.class.finabs");
@ -286,7 +298,8 @@ public class Modifiers {
} else {
// For non-interfaces
if (!validField(mod)) {
env.error(pos, "warn.invalid.modifier.field");
env.error(pos, "warn.invalid.modifier.field",
toString(mod & ~MM_FIELD, CF_Context.CTX_METHOD));
}
if (both(mod, ACC_FINAL, ACC_VOLATILE)) {
env.error(pos, "warn.invalid.modifier.fiva");
@ -329,7 +342,8 @@ public class Modifiers {
}
} else {
if (!validMethod(mod)) {
env.error(pos, "warn.invalid.modifier.mth");
env.error(pos, "warn.invalid.modifier.mth",
toString(mod & ~MM_METHOD, CF_Context.CTX_METHOD));
}
}
if (!validAccess(mod)) {
@ -403,10 +417,10 @@ public class Modifiers {
sb.append(Token.ABSTRACT.parsekey() + " ");
}
}
if ((context == CF_Context.CTX_CLASS || context == CF_Context.CTX_INNERCLASS || context == CF_Context.CTX_FIELD) && isFinal(mod)) {
if ( Set.of(CF_Context.CTX_CLASS, CF_Context.CTX_INNERCLASS, CF_Context.CTX_FIELD).contains(context) && isFinal(mod)) {
sb.append(Token.FINAL.parsekey() + " ");
}
if ((context == CF_Context.CTX_CLASS || context == CF_Context.CTX_INNERCLASS) && isInterface(mod)) {
if (Set.of(CF_Context.CTX_CLASS, CF_Context.CTX_INNERCLASS).contains(context) && isInterface(mod)) {
if (isAnnotation(mod)) {
sb.append(Token.ANNOTATION_ACCESS.parsekey() + " ");
}
@ -424,7 +438,7 @@ public class Modifiers {
if (isEnum(mod)) {
sb.append(Token.ENUM.parsekey() + " ");
}
if (context == CF_Context.CTX_METHOD && isMandated(mod)) {
if (Set.of(CF_Context.CTX_METHOD, CF_Context.CTX_FIELD).contains(context) && isMandated(mod)) {
sb.append(Token.MANDATED.parsekey() + " ");
}
@ -441,12 +455,10 @@ public class Modifiers {
sb.append("Deprecated(Pseudo) ");
}
return sb.toString();
return sb.toString().trim();
}
public static String moduleFlags( int flags ) {
return "";
}

@ -885,6 +885,47 @@ class Parser extends ParseBase {
}
}
/**
* Parse a Record entry
*/
private void parseRecord() throws Scanner.SyntaxError, IOException {
// Parses in the form:
// RECORD COMPONENT (, COMPONENT)*;
// where
// COMPONENT NAME:DESCRIPTOR SIGNATURE? (ANNOTATION)*
// NAME = (CPINDEX | IDENT)
// DESCRIPTOR = (CPINDEX | STRING)
// SIGNATURE = (CPINDEX | STRING)
debugScan("[Parser.parseRecord]: Begin ");
RecordData rd = cd.setRecord(scanner.pos);
Component:
while (true) {
ConstCell nameCell, descCell, signatureCell = null;
nameCell = parseName();
scanner.expect(Token.COLON);
descCell = parseName();
rd.addComponent(nameCell, descCell);
while (true) {
switch (scanner.token) {
case COMMA:
scanner.scan();
continue Component; // next component
case SEMICOLON:
return; // EOR
case ANNOTATION:
rd.setAnnotations( annotParser.scanAnnotations());
break;
default:
if( signatureCell != null ) {
env.error(scanner.pos, "warn.signature.repeated");
}
signatureCell = parseName();
rd.setComponentSignature(signatureCell);
}
}
} // end while
}
/**
* Parse an inner class.
*/
@ -1567,10 +1608,10 @@ class Parser extends ParseBase {
parseCPXBootstrapMethod();
break;
case NESTHOST:
if (cd.nestHostExists()) {
if (cd.nestHostAttributeExists()) {
env.error(scanner.pos, "extra.nesthost.attribute");
throw new Scanner.SyntaxError();
} else if (cd.nestMembersExist()) {
} else if (cd.nestMembersAttributesExist()) {
env.error(scanner.pos, "both.nesthost.nestmembers.found");
throw new Scanner.SyntaxError();
}
@ -1578,16 +1619,24 @@ class Parser extends ParseBase {
parseNestHost();
break;
case NESTMEMBERS:
if (cd.nestMembersExist()) {
if (cd.nestMembersAttributesExist()) {
env.error(scanner.pos, "extra.nestmembers.attribute");
throw new Scanner.SyntaxError();
} else if (cd.nestHostExists()) {
} else if (cd.nestHostAttributeExists()) {
env.error(scanner.pos, "both.nesthost.nestmembers.found");
throw new Scanner.SyntaxError();
}
scanner.scan();
parseNestMembers();
break;
case RECORD:
if( cd.recordAttributeExists() ) {
env.error(scanner.pos, "extra.record.attribute");
throw new Scanner.SyntaxError();
}
scanner.scan();
parseRecord();
break;
default:
env.error(scanner.pos, "field.expected");
throw new Scanner.SyntaxError();

@ -243,8 +243,6 @@ public class ParserAnnotation extends ParseBase {
}
/**
* scanAnnotations
*
* The main entry for parsing an annotation list.
*
* @return An ArrayList of parsed annotations
@ -358,7 +356,7 @@ public class ParserAnnotation extends ParseBase {
*/
protected void parseParamAnnots(int _totalParams, MethodData curMethod) throws Scanner.SyntaxError, IOException {
debugScan(" - - - > [ParserAnnotation.parseParamAnnots]: Begin, totalParams = " + _totalParams + " ");
// _The method thinks there are N+1 params in the signature
// The _method thinks there are N+1 params in the signature
// (N = total params in the call list) + 1 (return value)
int totalParams = _totalParams - 1;
TreeMap<Integer, ArrayList<AnnotationData>> pAnnots = new TreeMap<>();
@ -387,7 +385,7 @@ public class ParserAnnotation extends ParseBase {
// 3rd - parse either an optional ParamName, or a list of annotations
if (scanner.token == Token.PARAM_NAME) {
//parse the ParamName
scanParamName(_totalParams, iParamNum, curMethod);
scanParamName(totalParams, iParamNum, curMethod);
}
// 4th - parse each Annotation (followed by comma, followed by annotation

@ -0,0 +1,106 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
/**
* The record attribute (JEP 359 since class file 58.65535)
*/
public class RecordData extends AttrData {
private List<ComponentData> components = new ArrayList<>();
private ComponentData currentComp = null;
/* Record Data Fields */
public RecordData(ClassData cls) {
super(cls, Tables.AttrTag.ATT_Record.parsekey());
}
public void addComponent(ConstantPool.ConstCell nameCell, ConstantPool.ConstCell descCell) {
// Define a field if absent
FieldData fd = getClassData().addFieldIfAbsent(ACC_MANDATED & ACC_PRIVATE & ACC_FINAL, nameCell, descCell);
currentComp = new ComponentData(fd);
components.add(currentComp);
}
public void setComponentSignature(ConstantPool.ConstCell signature) {
currentComp.setSignature(signature);
}
public void setAnnotations(ArrayList<AnnotationData> annotations) {
currentComp.addAnnotations(annotations);
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out);
out.writeShort(components.size());
for (ComponentData cd : components) {
cd.write(out);
}
}
@Override
public int attrLength() {
int compsLength = components.stream().mapToInt(c -> c.getLength()).sum();
return 2 + compsLength;
}
class ComponentData extends MemberData {
private FieldData field;
private AttrData signature;
public ComponentData(FieldData field) {
super(getClassData());
this.field = field;
}
public void setSignature(ConstantPool.ConstCell value_cpx) {
signature = new CPXAttr(cls, Tables.AttrTag.ATT_Signature.parsekey(), value_cpx);
}
@Override
protected DataVector getAttrVector() {
return getDataVector(new ArrayList<>() {{
if (signature != null) {
add(signature);
}
}});
}
public void write(CheckedDataOutputStream out) throws IOException, Parser.CompilerError {
out.writeShort(field.getNameDesc().left.arg);
out.writeShort(field.getNameDesc().right.arg);
DataVector attrs = getAttrVector();
attrs.write(out);
}
public int getLength() {
return 4 + getAttrVector().getLength();
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019ß, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,6 @@
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
@ -179,7 +178,6 @@ public class Tables {
ConstantTypes.put(tt.value, tt);
}
/*-------------------------------------------------------- */
/**
* Attribute descriptor enums
*/
@ -229,7 +227,7 @@ public class Tables {
// u2 components_count;
// component_info components[components_count];
// }
ATT_Record (34, "ATT_Recrod", "Record");
ATT_Record (34, "ATT_Record", "Record");
private final Integer value;
private final String printval;
@ -643,7 +641,6 @@ public class Tables {
return retval;
}
/*-------------------------------------------------------- */
/**
* CF_Context enums
*/
@ -671,17 +668,4 @@ public class Tables {
return printval;
}
}
private static void registerAnnotElemType(CF_Context ctx) {
// NameToAnnotElemType.put(typ.printval, typ);
// AnnotElemTypes.put(typ.value, typ);
}
/*
public static CF_Context annotElemType(String idValue) {
return NameToAnnotElemType.get(idValue);
}
public static CF_Context annotElemType(int subtag) {
return AnnotElemTypes.get(subtag);
}
*/
}

@ -69,6 +69,8 @@ err.unbalanced.paren=Unbalanced parentheses.
err.package.repeated=Package statement repeated.
warn.intf.repeated=Interface {0} repeated.
warn.exc.repeated=Exception repeated in throws clause.
warn.signature.repeated=Signature attribute repeated in the record's component.
warn.record.repeated=Record attribute repeated.
err.multiple.inherit=Multiple inheritance is not supported.
err.toplevel.expected=Class, module or interface declaration expected.
err.const.def.expected=Constant declaration expected.
@ -77,11 +79,12 @@ err.const.redecl=Constant {0} redeclared.
warn.const0.redecl=Re-declaration of Constant #0 cannot be written to the class file.
#err.const.bsmindex=Bad Bootstrap Methods index {0} specified.
#warn.const.misused=Constant {0} was assumed to have another tag.
err.field.expected=Field, method, NestMembers or NestHost declaration expected.
err.field.expected=Field, method, NestMembers, NestHost or Record declaration expected.
err.token.expected={0} expected.
err.identifier.expected=Identifier expected.
err.extra.nesthost.attribute=There may be at most one NestHost attribute.
err.extra.nestmembers.attribute=There may be at most one NestMembers attribute.
err.extra.record.attribute=There may be at most one Record attribute.
err.both.nesthost.nestmembers.found=The attributes table of a ClassFile structure must not contain both a NestMembers attribute and a NestHost attribute.
err.name.expected=Name expected, got {0}.
err.module.name.expected=Module name expected, got {0}.
@ -119,21 +122,24 @@ warn.illslot=Local variable at Illegal slot {0}.
#warn.invalid.modifier=This modifier is not allowed here
warn.repeated.modifier=Repeated modifier.
warn.invalid.modifier.init=invalid modifier for <init> method \"{0}\".
warn.invalid.modifier.fiva=at most one of final and volatile modifiers can be used for a field.
warn.invalid.modifier.fiva=at most one of final and volatile modifiers can be used for a field
warn.invalid.modifier.intfield=interface field must be public static final only
warn.invalid.modifier.field=invalid modifier for a field.
warn.init.in_int=<init> method cannot be placed in an interface.
warn.invalid.modifier.intmth=interface method must be abstract public only \"{0}\".
warn.invalid.modifier.abst=invalid modifier for abstract method.
warn.invalid.modifier.mth=invalid modifier for a method.
#
warn.invalid.modifier.field=invalid modifier(s) for a field \"{0}\"
warn.invalid.modifier.mth=invalid modifier(s) for a method \"{0}\"
warn.invalid.modifier.innerclass=invalid modifier for an inner class \"{0}\"
#
warn.invalid.modifier.class=invalid modifier(s) for a class \"{0}\"
warn.invalid.modifier.int=invalid modifier(s) for an interface \"{0}\"
#
warn.invalid.modifier.acc=at most one of public, protected, and private modifiers can be used.
warn.invalid.modifier.int=invalid modifier(s) for an interface{0}
warn.invalid.modifier.int.abs=interface class must have abstract modifier.
warn.invalid.modifier.class=invalid modifier(s) for a class{0}
warn.missing.modifier.class=class or enum declaration missing.
warn.invalid.modifier.class.finabs=class cannot be both abstract and final.
warn.invalid.modifier.class.intenum=cannot be both interface and enum.
warn.invalid.modifier.innerclass=invalid modifier for an inner class \"{0}\".
err.itemtype.expected=StackMap item type expected instead of {0}.
err.localsmap.repeated=locals_map redeclared.
err.invalid.stack.frame.type=invalid stack frame type.

@ -39,8 +39,7 @@ import static org.openjdk.asmtools.jasm.Tables.AnnotElemType.AE_UNKNOWN;
import static org.openjdk.asmtools.jasm.TypeAnnotationUtils.*;
/**
*
*
* Class data of the Java Decoder
*/
class ClassData {
@ -139,11 +138,12 @@ class ClassData {
private void printUtf8InfoIndex(int index, String indexName) {
String name = (String) cpool[index];
out_print("#" + index + "; // " + String.format("%-16s",indexName));
out_print("#" + index + "; // ");
if (printDetails) {
out.print(" : " + name);
out.println(String.format("%-16s",indexName) + " : " + name);
} else {
out.println(indexName);
}
out.println();
}
/*========================================================*/
@ -728,7 +728,11 @@ class ClassData {
startArrayCmt(trap_num, "Traps");
try {
for (int i = 0; i < trap_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
out_println(in.readUnsignedShort() + " " +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + ";" +
getCommentPosCond());
}
} finally {
out_end("} // end Traps");
@ -740,11 +744,13 @@ class ClassData {
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_Exceptions:
int exc_num = in.readUnsignedShort();
startArrayCmt(exc_num, AttrName);
case ATT_NestMembers:
int count = in.readUnsignedShort();
startArrayCmt(count, AttrName);
try {
for (int i = 0; i < exc_num; i++) {
out_println("#" + in.readUnsignedShort() + ";" + getCommentPosCond());
for (int i = 0; i < count; i++) {
out_println("#" + in.readUnsignedShort() + ";" +
getCommentPosCond());
}
} finally {
out_end("}");
@ -755,7 +761,9 @@ class ClassData {
startArrayCmt(ll_num, AttrName);
try {
for (int i = 0; i < ll_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
out_println(in.readUnsignedShort() + " " +
in.readUnsignedShort() + ";" +
getCommentPosCond());
}
} finally {
out_end("}");
@ -767,7 +775,12 @@ class ClassData {
startArrayCmt(lvt_num, AttrName);
try {
for (int i = 0; i < lvt_num; i++) {
out_println(in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
out_println(in.readUnsignedShort() + " " +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + ";" +
getCommentPosCond());
}
} finally {
out_end("}");
@ -778,7 +791,10 @@ class ClassData {
startArrayCmt(ic_num, AttrName);
try {
for (int i = 0; i < ic_num; i++) {
out_println("#" + in.readUnsignedShort() + " #" + in.readUnsignedShort() + " #" + in.readUnsignedShort() + " " + in.readUnsignedShort() + ";" + getCommentPosCond());
out_println("#" + in.readUnsignedShort() + " #" +
in.readUnsignedShort() + " #" +
in.readUnsignedShort() + " " +
in.readUnsignedShort() + ";" + getCommentPosCond());
}
} finally {
out_end("}");
@ -968,12 +984,22 @@ class ClassData {
case ATT_NestHost:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_NestMembers:
int cls_num = in.readUnsignedShort();
startArrayCmt(cls_num, AttrName);
// MethodParameters_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u1 parameters_count;
// { u2 name_index;
// u2 access_flags;
// } parameters[parameters_count];
// }
case ATT_MethodParameters:
int pcount = in.readUnsignedByte();
startArrayCmtB(pcount, AttrName);
try {
for (int i = 0; i < cls_num; i++) {
out_println("#" + in.readUnsignedShort() + ";" + getCommentPosCond());
for (int i = 0; i < pcount; i++) {
out_println("#" + in.readUnsignedShort() + " " +
toHex(in.readUnsignedShort(), 2) + ";" +
getCommentPosCond());
}
} finally {
out_end("}");

@ -32,7 +32,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Main program of the Java DeCoder
* Main program of the Java DECoder :: class to jcod
*/
public class Main extends Tool {

@ -101,7 +101,7 @@ public class AnnotationData {
out.print(", ");
}
}
out.print("}");
out.print(tab + "}");
}
@Override

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,8 @@
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.JasmTokens;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
@ -73,10 +75,8 @@ public class BootstrapMethodData {
/*========================================================*/
/* Print Methods */
public void print() throws IOException {
out.print("BootstrapMethod ");
out.print("#" + bsm_index);
out.print(JasmTokens.Token.BOOTSTRAPMETHOD.parsekey() + " #" + bsm_index);
for (int i = 0; i < bsm_args_indexes.size(); i++) {
// cls.PrintConstant(bsm_args_indexes.elementAt(i));
out.print(" #" + bsm_args_indexes.get(i));
}
out.println(";");

@ -28,7 +28,6 @@ import org.openjdk.asmtools.jasm.Modifiers;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@ -43,96 +42,72 @@ public class ClassData extends MemberData {
// Owner of this ClassData
protected Tool tool;
/*-------------------------------------------------------- */
/* ClassData Fields */
// -----------------------------
// Header Info
// -----------------------------
/**
* Version info
*/
// Version info
protected int minor_version, major_version;
/**
* Constant Pool index to this class
*/
// Constant Pool index to this class
protected int this_cpx;
/**
* Constant Pool index to this classes parent (super)
*/
// Constant Pool index to this classes parent (super)
protected int super_cpx;
/**
* Constant Pool index to a file reference to the Java source
*/
// Constant Pool index to a file reference to the Java source
protected int source_cpx = 0;
/**
* The Constant Pool
*/
// -----------------------------
// The Constant Pool
// -----------------------------
protected ConstantPool pool;
/**
* The interfaces this class implements
*/
// -----------------------------
// Interfaces,Fields,Methods && Attributes
// -----------------------------
// The interfaces this class implements
protected int[] interfaces;
/**
* The fields of this class
*/
// The fields of this class
protected ArrayList<FieldData> fields;
/**
* The methods of this class
*/
// The methods of this class
protected ArrayList<MethodData> methods;
/**
* The inner-classes of this class
*/
// The record attribute of this class (since class file 58.65535)
protected RecordData record;
// The inner-classes of this class
protected ArrayList<InnerClassData> innerClasses;
/**
* The bootstrapmethods this class implements
*/
// The bootstrapmethods this class implements
protected ArrayList<BootstrapMethodData> bootstrapMethods;
/**
* The module this class file presents
*/
//The module this class file presents
protected ModuleData moduleData;
/**
* The NestHost of this class (since class file: 55.0)
*/
// The NestHost of this class (since class file: 55.0)
protected NestHostData nestHost;
/**
* The NestMembers of this class (since class file: 55.0)
*/
// The NestMembers of this class (since class file: 55.0)
protected NestMembersData nestMembers;
// other parsing fields
protected PrintWriter out;
protected String pkgPrefix = "";
private int pkgPrefixLen = 0;
private int length; //The number of elements in the buffer
private TextLines source = null;
private static final String initialTab = ""; //The number of elements in the buffer
/* -------------------------------------------------------- */
/* ClassData Methods */
public ClassData(PrintWriter out, Tool tool) {
this.out = out;
this.out = out;
this.tool = tool;
init(this);
memberType = "ClassData";
TraceUtils.traceln("printOptions=" + options.toString());
pool = new ConstantPool(this);
init(this);
}
/*========================================================*/
/* Read Methods */
public void read(File in) throws IOException {
read(new DataInputStream(new FileInputStream(in)));
}
@ -142,11 +117,7 @@ public class ClassData extends MemberData {
}
/**
*
* readFields
*
* read and resolve the field data
*
* Read and resolve the field data
*/
protected void readFields(DataInputStream in) throws IOException {
int nfields = in.readUnsignedShort();
@ -161,11 +132,7 @@ public class ClassData extends MemberData {
}
/**
*
* readMethods
*
* read and resolve the method data
*
* Read and resolve the method data
*/
protected void readMethods(DataInputStream in) throws IOException {
int nmethods = in.readUnsignedShort();
@ -180,11 +147,7 @@ public class ClassData extends MemberData {
}
/**
*
* readInterfaces
*
* read and resolve the interface data
*
* Read and resolve the interface data
*/
protected void readInterfaces(DataInputStream in) throws IOException {
// Read the interface names
@ -199,11 +162,7 @@ public class ClassData extends MemberData {
}
/**
*
* readAttributes
*
* read and resolve the attribute data
*
* Read and resolve the attribute data
*/
@Override
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
@ -253,6 +212,9 @@ public class ClassData extends MemberData {
// Read NestMembers Attribute (since class file: 55.0)
nestMembers = new NestMembersData(this).read(in, attrlen);
break;
case ATT_Record:
record = new RecordData(this).read(in);
break;
default:
handled = false;
break;
@ -261,15 +223,10 @@ public class ClassData extends MemberData {
}
/**
*
* read
*
* read and resolve the class data
*
* Read and resolve the class data
*/
public void read(DataInputStream in) throws IOException {
// Read the header
// -----------------------------------------------
int magic = in.readInt();
if (magic != JAVA_MAGIC) {
throw new ClassFormatError("wrong magic: " + HexUtils.toHex(magic) + ", expected " + HexUtils.toHex(JAVA_MAGIC));
@ -278,40 +235,33 @@ public class ClassData extends MemberData {
major_version = in.readUnsignedShort();
// Read the constant pool
// -----------------------------------------------
pool.read(in);
access = in.readUnsignedShort(); // & MM_CLASS; // Q
this_cpx = in.readUnsignedShort();
super_cpx = in.readUnsignedShort();
TraceUtils.traceln("access=" + access + " " + Modifiers.accessString(access, CF_Context.CTX_INNERCLASS) + " this_cpx=" + this_cpx + " super_cpx=" + super_cpx);
TraceUtils.traceln("access=" + access + " " + Modifiers.accessString(access, CF_Context.CTX_INNERCLASS) +
" this_cpx=" + this_cpx +
" super_cpx=" + super_cpx);
// Read the interfaces
// -----------------------------------------------
readInterfaces(in);
// Read the fields
// -----------------------------------------------
readFields(in);
// Read the methods
// -----------------------------------------------
readMethods(in);
// Read the attributes
readAttributes(in);
TraceUtils.traceln("");
TraceUtils.traceln("--------------------------------------------------------------------");
TraceUtils.traceln("Reading is done-----------------------------------------------------");
TraceUtils.traceln("");
}
/*========================================================*/
/**
*
* getSrcLine
*
* read and resolve the attribute data
*
* Read and resolve the attribute data
*/
public String getSrcLine(int lnum) {
if (source == null) {
@ -426,7 +376,7 @@ printSugar:
out.print("deprecated ");
}
if (options.contains(Options.PR.CPX)) {
out.print("\t#" + this_cpx + "; //");
out.print("\t#" + this_cpx + " //");
}
pool.PrintConstant(out, this_cpx);
}
@ -490,6 +440,12 @@ printSugar:
}
out.println();
}
// Print the Record (since class file 58.65535 JEP 359)
if( record != null && !record.isEmpty()) {
record.print();
}
// Print the NestHost (since class file: 55.0)
if(nestHost != null) {
nestHost.print();

@ -24,6 +24,8 @@ package org.openjdk.asmtools.jdis;
import static org.openjdk.asmtools.jasm.Tables.*;
import static org.openjdk.asmtools.jasm.OpcodeTables.*;
import static org.openjdk.asmtools.jdis.Utils.commentString;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
@ -388,6 +390,10 @@ public class CodeData {
cls.pool.PrintConstant(out, cpx);
}
private void PrintCommentedConstant(int cpx) {
out.print(commentString(cls.pool.ConstantStrValue(cpx)));
}
private int printInstr(int pc) {
boolean pr_cpx = meth.options.contains(Options.PR.CPX);
int opc = getUbyte(pc);
@ -577,8 +583,8 @@ public class CodeData {
// getUbyte(pc + 3); // reserved byte
// getUbyte(pc + 4); // reserved byte
if (pr_cpx) {
out.print("\t#" + index + "; //");
PrintConstant(index);
out.print("\t#" + index + ";\t");
PrintCommentedConstant(index);
} else {
PrintConstant(index);
}

@ -33,6 +33,8 @@ import java.util.Hashtable;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static org.openjdk.asmtools.jdis.Utils.commentString;
/**
*
* ConstantPool
@ -598,6 +600,8 @@ public class ConstantPool {
return str;
}
@Override
public void print(PrintWriter out) {
super.print(out);
@ -615,7 +619,7 @@ public class ConstantPool {
break;
case CONSTANT_DYNAMIC:
case CONSTANT_INVOKEDYNAMIC:
out.println(value1 + ":#" + value2 + ";\t// " + stringVal());
out.println(value1 + ":#" + value2 + ";\t" + commentString(stringVal()));
break;
default:
break;
@ -1060,22 +1064,14 @@ public class ConstantPool {
}
/**
*
* print
*
* prints the Constant value at a given CP index.
*
*/
void PrintConstant(PrintWriter out, int cpx) {
out.print(ConstantStrValue(cpx));
}
/**
*
* printlnClassId
*
* prints a constant value, with the print format based on the print options.
*
*/
public void printlnClassId(PrintWriter out, int cpx) throws IOException {
printlnClassId(out, cpx, false);

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,43 +23,34 @@
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.Modifiers;
import static org.openjdk.asmtools.jasm.Tables.*;
import java.io.DataInputStream;
import java.io.IOException;
import static org.openjdk.asmtools.jasm.Tables.AttrTag;
import static org.openjdk.asmtools.jasm.Tables.CF_Context;
/**
* Field data for field members in a class of the Java Disassembler
*/
public class FieldData extends MemberData {
/*-------------------------------------------------------- */
/* FieldData Fields */
/**
* CP index to the field name
*/
// CP index to the field name
protected int name_cpx;
/**
* CP index to the field type
*/
// CP index to the field type
protected int sig_cpx;
/**
* CP index to the field value
*/
// CP index to the field value
protected int value_cpx = 0;
public static final String initialTab = "";
/*-------------------------------------------------------- */
public FieldData(ClassData cls) {
init(cls);
super(cls);
memberType = "FieldData";
}
/*========================================================*/
/* Read Methods */
@Override
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
// Read the Attributes
@ -79,12 +70,8 @@ public class FieldData extends MemberData {
}
/**
*
* read
*
* read and resolve the field data called from ClassData. precondition: NumFields has
* already been read from the stream.
*
* Read and resolve the field data called from ClassData.
* Precondition: NumFields has already been read from the stream.
*/
public void read(DataInputStream in) throws IOException {
// read the Fields CP indexes
@ -96,17 +83,10 @@ public class FieldData extends MemberData {
// Read the attributes
readAttributes(in);
} // end read
}
/*========================================================*/
/* Print Methods */
/**
*
* print
*
* prints the field data to the current output stream. called from ClassData.
* precondition: NumFields has already been printed to the stream.
*
* Prints the field data to the current output stream. called from ClassData.
*/
public void print() throws IOException {
// Print annotations first

@ -26,12 +26,12 @@ import org.openjdk.asmtools.common.Tool;
import org.openjdk.asmtools.util.I18NResourceBundle;
import org.openjdk.asmtools.util.ProductInfo;
import java.io.*;
import java.io.DataInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.function.Consumer;
/**
* Main program of the Java Disassembler :: class -> jasm
* Main program of the Java Disassembler :: class to jasm
*/
public class Main extends Tool {

@ -29,7 +29,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
/**
*
* Base class for ClassData, MethodData, FieldData and RecordData(JEP 360)
*/
public class MemberData {
@ -43,27 +43,27 @@ public class MemberData {
protected boolean isDeprecated = false;
/**
* The visible annotations for this class
* The visible annotations for this class, member( field or method) or record component
*/
protected ArrayList<AnnotationData> visibleAnnotations;
/**
* The invisible annotations for this class
* The invisible annotations for this class, member( field or method) or record component
*/
protected ArrayList<AnnotationData> invisibleAnnotations;
/**
* The visible annotations for this class
* The visible annotations for this class, member( field or method) or record component
*/
protected ArrayList<TypeAnnotationData> visibleTypeAnnotations;
/**
* The invisible annotations for this class
* The invisible annotations for this class, member( field or method) or record component
*/
protected ArrayList<TypeAnnotationData> invisibleTypeAnnotations;
/**
* The remaining attributes of this class
* The remaining attributes of this class, member( field or method) or record component
*/
protected ArrayList<AttrData> attrs;
@ -73,8 +73,10 @@ public class MemberData {
protected PrintWriter out;
protected String memberType = "";
/* -------------------------------------------------------- */
/* ClassData Methods */
public MemberData(ClassData cls) {
init(cls);
}
public MemberData() {
}
@ -83,7 +85,6 @@ public class MemberData {
this.cls = cls;
this.options = cls.options;
}
protected boolean handleAttributes(DataInputStream in, Tables.AttrTag attrtag, int attrlen) throws IOException {
// sub-classes override
return false;

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -39,22 +39,9 @@ public class MethodData extends MemberData {
/*-------------------------------------------------------- */
/* MethodData Fields */
/**
* MethodParamData
*/
class ParamNameData {
public int access;
public int name_cpx;
public ParamNameData(int name, int access) {
this.access = access;
this.name_cpx = name;
}
}
public static final String initialTab = "";
/*-------------------------------------------------------- */
/**
* CP index to the method name
*/
@ -64,43 +51,34 @@ public class MethodData extends MemberData {
* CP index to the method type
*/
protected int sig_cpx;
protected String lP; // labelPrefix
/**
* The parameter names for this method
*/
protected ArrayList<ParamNameData> paramNames;
/**
* The visible parameter annotations for this method
*/
protected ParameterAnnotationData visibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected ParameterAnnotationData invisibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected AnnotElem.AnnotValue defaultAnnotation;
/**
* The code data for this method. May be null
*/
private CodeData code;
/**
* The exception table (thrown exceptions) for this method. May be null
*/
private int[] exc_table = null;
protected String lP; // labelPrefix
public static final String initialTab = "";
/**
* The parameter names for this method
*/
protected ArrayList<ParamNameData> paramNames;
/**
* The visible parameter annotations for this method
*/
protected ParameterAnnotationData visibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected ParameterAnnotationData invisibleParameterAnnotations;
/**
* The invisible parameter annotations for this method
*/
protected AnnotElem.AnnotValue defaultAnnotation;
/*-------------------------------------------------------- */
public MethodData(ClassData cls) {
init(cls);
super(cls);
memberType = "MethodData";
lP = (options.contains(Options.PR.LABS)) ? "L" : "";
paramNames = null;
@ -145,12 +123,9 @@ public class MethodData extends MemberData {
}
/**
*
* read
*
* read and resolve the method data called from ClassData. precondition: NumFields has
* already been read from the stream.
*
* read and resolve the method data called from ClassData.
* Precondition: NumFields has already been read from the stream.
*/
public void read(DataInputStream in) throws IOException {
// read the Methods CP indexes
@ -190,15 +165,11 @@ public class MethodData extends MemberData {
}
}
/*========================================================*/
/* Print Methods */
/**
*
* printPAnnotations
*
* <p>
* prints the parameter annotations for this method. called from CodeAttr (since JASM
* code integrates the PAnnotation Syntax inside the method body).
*
*/
// This is called from the CodeAttr
public void printPAnnotations() throws IOException {
@ -289,13 +260,11 @@ public class MethodData extends MemberData {
}
/*========================================================*/
/* Print Methods */
/**
*
* print
*
* prints the method data to the current output stream. called from ClassData.
* precondition: NumMethods has already been printed to the stream.
*
* Prints the method data to the current output stream. called from ClassData.
*/
public void print(boolean skipBlankLine) throws IOException {
// Print the Annotations
@ -349,32 +318,23 @@ public class MethodData extends MemberData {
if (pr_cpx) {
// print the CPX method descriptor
out.print("#" + name_cpx + ":#" + sig_cpx);
out.print("\t // ");
out.println(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
out.print("#" + name_cpx + ":#" + sig_cpx +
((code == null && exc_table == null && defaultAnnotation == null) ? ";" : "") +
"\t // " + cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
} else {
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx) +
((code == null && exc_table == null && defaultAnnotation == null) ? ";" : ""));
}
// followed by default annotation
if (defaultAnnotation != null) {
out.print(" default { ");
defaultAnnotation.print(out, initialTab);
out.print(" } ");
out.print(" }" + ((code == null && exc_table == null) ? ";" : " "));
}
// followed by exception table
printExceptionTable();
// if ((code == null) || ((access & ACC_ABSTRACT) != 0)) {
if (code == null) {
out.print(";");
if (pr_cpx) {
out.print("\t // ");
out.print(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(sig_cpx));
}
out.println("");
} else {
if (code != null) {
code.print();
}
}
@ -391,5 +351,19 @@ public class MethodData extends MemberData {
}
}
}
} // end MethodData
/**
* MethodParamData
*/
class ParamNameData {
public int access;
public int name_cpx;
public ParamNameData(int name, int access) {
this.access = access;
this.name_cpx = name;
}
}
} // end MethodData

@ -23,6 +23,8 @@
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.JasmTokens;
import java.io.DataInputStream;
import java.io.IOException;
@ -50,7 +52,7 @@ public class NestHostData {
public void print() {
boolean pr_cpx = options.contains(Options.PR.CPX);
cls.out.print("NestHost ");
cls.out.print(JasmTokens.Token.NESTHOST.parsekey() + " ");
if (pr_cpx) {
cls.out.print("#" + host_class_index + "; //");
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -22,6 +22,8 @@
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.JasmTokens;
import java.io.DataInputStream;
import java.io.IOException;
@ -55,7 +57,7 @@ public class NestMembersData {
String indexes = "";
String names = "";
boolean pr_cpx = options.contains(Options.PR.CPX);
cls.out.print("NestMembers ");
cls.out.print(JasmTokens.Token.NESTMEMBERS.parsekey() + " ");
for(int i = 0; i< classes.length; i++) {
if (pr_cpx) {
indexes += (indexes.isEmpty() ? "" : ", ") + "#" + classes[i];

@ -0,0 +1,206 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import org.openjdk.asmtools.jasm.JasmTokens;
import org.openjdk.asmtools.jasm.Tables;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static org.openjdk.asmtools.jdis.TraceUtils.traceln;
/**
* The Record attribute data
* <p>
* since class file 58.65535 (JEP 359)
*/
public class RecordData {
private final ClassData cls;
private final boolean pr_cpx = Options.OptionObject().contains(Options.PR.CPX);
private String initialTab = " ";
private List<Component> components;
public RecordData(ClassData cls) {
this.cls = cls;
}
public RecordData read(DataInputStream in) throws IOException {
int count = in.readUnsignedShort();
traceln("components=" + count);
components = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
components.add(new Component(cls).read(in));
}
return this;
}
/**
* Prints the record data to the current output stream. called from ClassData.
*/
public void print() throws IOException {
int bound = components.size()-1;
cls.out.println(JasmTokens.Token.RECORD.parsekey());
for(int cn = 0; cn <= bound; cn++) {
components.get(cn).print( cn == bound ? ";" : ",");
}
cls.out.println();
}
public boolean isEmpty() {
return components.isEmpty();
}
private class Component extends MemberData {
// CP index to the name
private int name_cpx;
// CP index to the descriptor
private int desc_cpx;
// Signature can be located in component_info
private SignatureData signature;
//
private int countAttr = 0;
public Component(ClassData cls) {
super(cls);
memberType = "RecordData";
}
@Override
protected boolean handleAttributes(DataInputStream in, Tables.AttrTag attrtag, int attrlen) throws IOException {
// Read the Attributes
boolean handled = true;
switch (attrtag) {
case ATT_Signature:
if( signature != null ) {
traceln("Record attribute: more than one attribute Signature are in component.attribute_info_attributes[attribute_count]");
traceln("Last one will be used.");
}
signature = new SignatureData(cls).read(in, attrlen);
break;
default:
handled = false;
break;
}
return handled;
}
/**
* Read and resolve the component data called from ClassData.
*/
public Component read(DataInputStream in) throws IOException {
// read the Component CP indexes
name_cpx = in.readUnsignedShort();
desc_cpx = in.readUnsignedShort();
traceln(" RecordComponent: name[" + name_cpx + "]=" + cls.pool.getString(name_cpx)
+ " descriptor[" + desc_cpx + "]=" + cls.pool.getString(desc_cpx));
// Read the attributes
readAttributes(in);
// Calculate amount of attributes
countAttr = (visibleAnnotations == null ? 0 : visibleAnnotations.size()) +
(invisibleAnnotations == null ? 0 : invisibleAnnotations.size()) +
(visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size()) +
(invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations.size()) +
(signature != null ? 1 : 0);
return this;
}
public boolean isEmpty() {
return countAttr == 0;
}
private void printAnnotations(String endOfComponent) {
if( signature != null ) {
signature.print(initialTab);
countAttr--;
if(countAttr != 0)
out.println();
}
if (visibleAnnotations != null) {
for (AnnotationData visad : visibleAnnotations) {
// out.print(initialTab);
visad.print(out, initialTab);
countAttr--;
if(countAttr != 0)
out.println();
}
}
if (invisibleAnnotations != null) {
for (AnnotationData invisad : invisibleAnnotations) {
invisad.print(out, initialTab);
countAttr--;
if(countAttr != 0)
out.println();
}
}
if (visibleTypeAnnotations != null) {
for (TypeAnnotationData visad : visibleTypeAnnotations) {
visad.print(out, initialTab);
countAttr--;
if(countAttr != 0)
out.println();
}
}
if (invisibleTypeAnnotations != null) {
for (TypeAnnotationData invisad : invisibleTypeAnnotations) {
invisad.print(out, initialTab);
countAttr--;
if(countAttr != 0)
out.println();
}
}
out.println(endOfComponent);
}
/**
* Prints the component data to the current output stream. called from RecordData.
*/
public void print(String endOfComponent) throws IOException {
out.print(initialTab);
if (isSynthetic) {
out.print("synthetic ");
}
if (isDeprecated) {
out.print("deprecated ");
}
if (pr_cpx) {
out.print("#" + name_cpx + ":#" + desc_cpx + (isEmpty() ? endOfComponent : ""));
out.println("\t // " + cls.pool.getName(name_cpx) + ":" + cls.pool.getName(desc_cpx));
} else {
out.println(cls.pool.getName(name_cpx) + ":" + cls.pool.getName(desc_cpx) + (isEmpty() ? endOfComponent : ""));
}
// print component's attributes
if (!isEmpty()) {
printAnnotations(endOfComponent);
}
}
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.asmtools.jdis;
import java.io.DataInputStream;
import java.io.IOException;
/**
* The Signature attribute data
* <p>
* since class file 49.0
*/
public class SignatureData {
ClassData cls;
int signature_index;
private Options options = Options.OptionObject();
public SignatureData(ClassData cls) {
this.cls = cls;
}
public SignatureData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError {
if (attribute_length != 2) {
throw new ClassFormatError("ATT_Signature: Invalid attribute length");
}
signature_index = in.readUnsignedShort();
return this;
}
public void print(String initialTab) {
boolean pr_cpx = options.contains(Options.PR.CPX);
if (pr_cpx) {
cls.out.print(initialTab + "#" + signature_index + "\t\t // Signature: " + cls.pool.StringValue(signature_index));
} else {
cls.out.print(initialTab + cls.pool.StringValue(signature_index));
}
}
}

@ -67,4 +67,12 @@ fullname:
return retval;
}
static public String commentString(String str) {
return commentString(str,"// ");
}
static public String commentString(String str, String prefix) {
return prefix + str.replace("\n", "\n" + prefix);
}
}

@ -1,4 +1,4 @@
# Copyright (c) 2014, 2017 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2019 Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -20,7 +20,7 @@
# questions.
jdis.usage=\
Usage: java -jar asmtools.jar jdis [options] FILE.class...\n\
Usage: java -jar asmtools.jar jdis [options] FILE.class... > FILE.jasm\n\
where possible options include:
jdis.opt.g=\