CODETOOLS-7902525 Asmtools support: JEP 360 Sealed Types(Preview)

This commit is contained in:
lkuskov 2020-02-03 16:54:39 -08:00
parent a136ef54ee
commit 79096622a1
17 changed files with 496 additions and 186 deletions

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, 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.List;
/**
* Base class of the "classes[]" data of attributes
* <p>
* JEP 181 (Nest-based Access Control): class file 55.0
* NestMembers_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 number_of_classes;
* u2 classes[number_of_classes];
* }
* <p>
* JEP 360 (Sealed types): class file 59.65535
* PermittedSubtypes_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 permitted_subtypes_count;
* u2 classes[permitted_subtypes_count];
* }
*/
public class ClassArrayAttr extends AttrData {
List<ConstantPool.ConstCell> classes;
public ClassArrayAttr(String attributeName, ClassData cdata, List<ConstantPool.ConstCell> classes) {
super(cdata, attributeName);
this.classes = classes;
}
@Override
public int attrLength() {
return 2 + classes.size() * 2;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out);
out.writeShort(classes.size());
for (ConstantPool.ConstCell c : classes) {
out.writeShort(c.arg);
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -55,6 +55,9 @@ class ClassData extends MemberData {
// JEP 359 - Record attribute since class file 58.65535
private RecordData recordData;
// JEP 360 - PermittedSubtypes attribute since class file 59.65535
private PermittedTypesAttr permittedTypesAttr;
ModuleAttr moduleAttribute = null;
Environment env;
protected ConstantPool pool;
@ -296,11 +299,17 @@ class ClassData extends MemberData {
nestHostAttr = new CPXAttr(this, AttrTag.ATT_NestHost.parsekey(), hostClass);
}
public void addNestMembers(List<ConstantPool.ConstCell> nestMemberClasses) {
public void addNestMembers(List<ConstantPool.ConstCell> classes) {
env.traceln("addNestMembers");
nestMembersAttr = new NestMembersAttr(this, nestMemberClasses);
nestMembersAttr = new NestMembersAttr(this, classes);
}
public void addPermittedSubtypes(List<ConstantPool.ConstCell> classes) {
env.traceln("addPermittedSubtypes");
permittedTypesAttr = new PermittedTypesAttr(this, classes);
}
public void endClass() {
sourceFileNameAttr = new CPXAttr(this,
AttrTag.ATT_SourceFile.parsekey(),
@ -442,6 +451,9 @@ class ClassData extends MemberData {
attrs.add(nestHostAttr);
if(nestMembersAttributesExist())
attrs.add(nestMembersAttr);
// since class version 59.65535 (JEP 360)
if ( permittedSubtypesAttributesExist() )
attrs.add(permittedTypesAttr);
}
return attrs;
}
@ -496,6 +508,8 @@ class ClassData extends MemberData {
public boolean nestMembersAttributesExist() { return nestMembersAttr != null; }
public boolean permittedSubtypesAttributesExist() { return permittedTypesAttr != null; }
public boolean recordAttributeExists() { return recordData != null; }
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -308,10 +308,12 @@ public class JasmTokens {
// Declaration keywords
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),
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),
RECORD (175, "RECORD", "Record", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),
//
PERMITTEDSUBTYPES (176, "PERMITTEDSUBTYPES", "PermittedSubtypes", 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),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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,33 +22,20 @@
*/
package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.List;
/**
* The NestMembers attribute data
* <p>
* since class file 55.0 (JEP 181)
* The "classes[]" data of attributes
* JEP 181 (Nest-based Access Control): class file 55.0
* NestMembers_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 number_of_classes;
* u2 classes[number_of_classes];
* }
*/
public class NestMembersAttr extends AttrData {
List<ConstantPool.ConstCell> nestMembers;
public NestMembersAttr(ClassData cdata, List<ConstantPool.ConstCell> nestMembers){
super(cdata, Tables.AttrTag.ATT_NestMembers.parsekey());
this.nestMembers = nestMembers;
}
@Override
public int attrLength() {
return 2 + nestMembers.size() * 2;
}
@Override
public void write(CheckedDataOutputStream out) throws IOException {
super.write(out);
out.writeShort(nestMembers.size());
for (ConstantPool.ConstCell c : nestMembers) {
out.writeShort(c.arg);
}
public class NestMembersAttr extends ClassArrayAttr {
public NestMembersAttr(ClassData cdata, List<ConstantPool.ConstCell> classes) {
super(Tables.AttrTag.ATT_NestMembers.parsekey(), cdata, classes);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -369,7 +369,7 @@ class Parser extends ParseBase {
// either a CONSTANT_Methodref_info structure or a CONSTANT_InterfaceMethodref_info structure (§4.4.2)
// representing a class's or interface's method for which a method handle is to be created.
ConstType ctype = ConstType.CONSTANT_METHOD;
if ( this.cd.cfv.major_version() >= 52 && Modifiers.isInterface(this.cd.access) ) {
if (this.cd.cfv.major_version() >= 52 && Modifiers.isInterface(this.cd.access)) {
ctype = ConstType.CONSTANT_INTERFACEMETHOD;
}
refCell = pool.FindCell(cpParser.parseConstValue(ctype));
@ -561,28 +561,67 @@ class Parser extends ParseBase {
while (true) {
nextmod = 0;
switch (scanner.token) {
case PUBLIC: nextmod = ACC_PUBLIC; break;
case PRIVATE: nextmod = ACC_PRIVATE; break;
case PROTECTED: nextmod = ACC_PROTECTED; break;
case STATIC: nextmod = ACC_STATIC; break;
case FINAL: nextmod = ACC_FINAL; break;
case SYNCHRONIZED: nextmod = ACC_SYNCHRONIZED; break;
case SUPER: nextmod = ACC_SUPER; break;
case VOLATILE: nextmod = ACC_VOLATILE; break;
case BRIDGE: nextmod = ACC_BRIDGE; break;
case TRANSIENT: nextmod = ACC_TRANSIENT; break;
case VARARGS: nextmod = ACC_VARARGS; break;
case NATIVE: nextmod = ACC_NATIVE; break;
case INTERFACE: nextmod = ACC_INTERFACE; break;
case ABSTRACT: nextmod = ACC_ABSTRACT; break;
case STRICT: nextmod = ACC_STRICT; break;
case ENUM: nextmod = ACC_ENUM; break;
case SYNTHETIC: nextmod = ACC_SYNTHETIC; break;
case PUBLIC:
nextmod = ACC_PUBLIC;
break;
case PRIVATE:
nextmod = ACC_PRIVATE;
break;
case PROTECTED:
nextmod = ACC_PROTECTED;
break;
case STATIC:
nextmod = ACC_STATIC;
break;
case FINAL:
nextmod = ACC_FINAL;
break;
case SYNCHRONIZED:
nextmod = ACC_SYNCHRONIZED;
break;
case SUPER:
nextmod = ACC_SUPER;
break;
case VOLATILE:
nextmod = ACC_VOLATILE;
break;
case BRIDGE:
nextmod = ACC_BRIDGE;
break;
case TRANSIENT:
nextmod = ACC_TRANSIENT;
break;
case VARARGS:
nextmod = ACC_VARARGS;
break;
case NATIVE:
nextmod = ACC_NATIVE;
break;
case INTERFACE:
nextmod = ACC_INTERFACE;
break;
case ABSTRACT:
nextmod = ACC_ABSTRACT;
break;
case STRICT:
nextmod = ACC_STRICT;
break;
case ENUM:
nextmod = ACC_ENUM;
break;
case SYNTHETIC:
nextmod = ACC_SYNTHETIC;
break;
case ANNOTATION_ACCESS:
nextmod = ACC_ANNOTATION; break;
nextmod = ACC_ANNOTATION;
break;
case DEPRECATED: nextmod = DEPRECATED_ATTRIBUTE; break;
case MANDATED: nextmod = ACC_MANDATED; break;
case DEPRECATED:
nextmod = DEPRECATED_ATTRIBUTE;
break;
case MANDATED:
nextmod = ACC_MANDATED;
break;
default:
return nextmod;
}
@ -865,20 +904,21 @@ class Parser extends ParseBase {
}
/**
* Parse a NestMembers entry
* Parse a list of classes belonging to the [NestMembers | PermittedSubtypes] entry
*/
private void parseNestMembers() throws Scanner.SyntaxError, IOException {
ArrayList<ConstCell> nestMembers = new ArrayList<>();
private void parseClasses(Consumer<ArrayList<ConstCell>> classesConsumer)
throws Scanner.SyntaxError, IOException {
ArrayList<ConstCell> classes = new ArrayList<>();
// Parses in the form:
// NESTMEMBERS IDENT(, IDENT)*;
debugStr(" [Parser.parseNestMembers]: <<<Begin>>>");
// (NESTMEMBERS|PERMITTEDSUBTYPES)? IDENT(, IDENT)*;
debugStr(" [Parser.parseClasses]: <<<Begin>>>");
while (true) {
String className = prependPackage(parseIdent(), true);
nestMembers.add(pool.FindCellClassByName(className));
debugScan(" [Parser.parseNestMembers]: NestMembers: class " + className);
classes.add(pool.FindCellClassByName(className));
debugScan(" [Parser.parseClasses]: class " + className);
if (scanner.token != Token.COMMA) {
scanner.expect(Token.SEMICOLON);
cd.addNestMembers(nestMembers);
classesConsumer.accept(classes);
return;
}
scanner.scan();
@ -886,7 +926,7 @@ class Parser extends ParseBase {
}
/**
* Parse a Record entry
* Parse the Record entry
*/
private void parseRecord() throws Scanner.SyntaxError, IOException {
// Parses in the form:
@ -898,7 +938,7 @@ class Parser extends ParseBase {
// SIGNATURE = (CPINDEX | STRING)
debugScan("[Parser.parseRecord]: Begin ");
RecordData rd = cd.setRecord(scanner.pos);
Component:
Component:
while (true) {
ConstCell nameCell, descCell, signatureCell = null;
nameCell = parseName();
@ -913,10 +953,10 @@ Component:
case SEMICOLON:
return; // EOR
case ANNOTATION:
rd.setAnnotations( annotParser.scanAnnotations());
rd.setAnnotations(annotParser.scanAnnotations());
break;
default:
if( signatureCell != null ) {
if (signatureCell != null) {
env.error(scanner.pos, "warn.signature.repeated");
}
signatureCell = parseName();
@ -1627,10 +1667,18 @@ Component:
throw new Scanner.SyntaxError();
}
scanner.scan();
parseNestMembers();
parseClasses(list -> cd.addNestMembers(list));
break;
case RECORD:
if( cd.recordAttributeExists() ) {
case PERMITTEDSUBTYPES: // JEP 360
if (cd.nestMembersAttributesExist()) {
env.error(scanner.pos, "extra.permittedsubtypes.attribute");
throw new Scanner.SyntaxError();
}
scanner.scan();
parseClasses(list -> cd.addPermittedSubtypes(list));
break;
case RECORD: // JEP 359
if (cd.recordAttributeExists()) {
env.error(scanner.pos, "extra.record.attribute");
throw new Scanner.SyntaxError();
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2018, 2020, 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.util.List;
/**
* The "classes[]" data of attributes
* JEP 360 (Sealed types): class file 59.65535
* PermittedSubtypes_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 permitted_subtypes_count;
* u2 classes[permitted_subtypes_count];
* }
*/
public class PermittedTypesAttr extends ClassArrayAttr {
public PermittedTypesAttr(ClassData cdata, List<ConstantPool.ConstCell> classes) {
super(Tables.AttrTag.ATT_PermittedSubtypes.parsekey(), cdata, classes);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -227,7 +227,15 @@ public class Tables {
// u2 components_count;
// component_info components[components_count];
// }
ATT_Record (34, "ATT_Record", "Record");
ATT_Record (34, "ATT_Record", "Record"),
// JEP 360 (Sealed types): class file 59.65535
// PermittedSubtypes_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 permitted_subtypes_count;
// u2 classes[permitted_subtypes_count];
// }
ATT_PermittedSubtypes (35, "ATT_PermittedSubtypes", "PermittedSubtypes");
private final Integer value;
private final String printval;

View File

@ -1,4 +1,4 @@
# Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2020, 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
@ -77,23 +77,20 @@ err.const.def.expected=Constant declaration expected.
err.const.undecl=Constant #{0} not declared.
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, 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.permittedsubtypes.attribute=There may be at most one PermittedSubtypes 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}.
err.int.expected=Integer expected.
err.neg.forbidden=Negative integer is not allowed here.
err.value.large=Value doesn't fit in {0}.
err.value.expected=Value expected.
err.wrong.mnemocode=Invalid mnemocode ({0}).
#err.class.expected='class' or 'interface' keyword expected.
err.default.redecl=Default statement already declared in this table.
err.long.switchtable=Switchtable too long: > {0}.
err.io.exception=I/O error in {0}.
@ -117,9 +114,7 @@ err.cannot.write=Cannot write to {0}.
err.msig.malformed=Malformed method signature at char {0}. [err={1}]
err.no.classname=Class name not defined.
warn.msig.more255=Number of parameters too large ({0}>255).
#warn.msig.large=Number of parameters ({0}) exceeds max_locals value ({1}).
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
@ -155,10 +150,7 @@ err.stackmap.repeated=stack_map redeclared.
err.version.expected=class file version expected
err.invalid.innerclass=Invalid declaration of Inner Class
err.invalid.bootstrapmethod=Invalid declaration of BootstrapMethod Entry
#err.table.expected=Table expected
#err.package.module.expected=package or module expected
err.frametype.repeated=Frametype repeated
#err.module.expected=module expected
err.invalid.paramnum=Invalid Parameter Number: {0}.
err.duplicate.paramnum=Duplicate Parameter Number: {0}.
err.paramname.constnum.invaltype=ParameterName CPX at {0} is not a ConstantString.
@ -188,7 +180,6 @@ warn.dot.will.be.converted=Forward slash \"/\" expected instead of dot \".\". Th
#
# Compiler Errors
#
# comperr.hashcode.err="CV hash:{0}"
comperr.constcell.nullvalset="Cell without value in setCell"
comperr.constcell.nullvalhash="Cell without value in cpoolHashByValue"
comperr.constcell.invarg="Cell[{0}] has #{1}"

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, 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
@ -262,7 +262,7 @@ class ClassData {
}
}
private void printCP(PrintWriter out) throws IOException {
private void printCP(PrintWriter out) {
int length = CPlen;
startArrayCmt(length, "Constant Pool");
out_println("; // first element is empty");
@ -273,7 +273,7 @@ class ClassData {
byte btag = types[i];
ConstType tg = tag(btag);
int pos = cpe_pos[i];
String tagstr = "";
String tagstr;
String valstr;
int v1;
long lv;
@ -359,14 +359,6 @@ class ClassData {
return " at " + toHex(countedin.getPos());
}
private String getStringPosCond() {
if (printDetails) {
return getStringPos();
} else {
return "";
}
}
private String getCommentPosCond() {
if (printDetails) {
return " // " + getStringPos();
@ -384,16 +376,16 @@ class ClassData {
out_println("// invalid length of " + attrname + " attr: " + len + " (should be " + (expectedIndices * 2) + ") > ");
printBytes(out, in, len);
} else {
String outputString = "";
StringBuilder outputString = new StringBuilder();
for (int k = 1; k <= expectedIndices; k++) {
outputString += ("#" + in.readUnsignedShort() + "; ");
outputString.append("#").append(in.readUnsignedShort()).append("; ");
if (k % 16 == 0) {
out_println(outputString.replaceAll("\\s+$",""));
outputString = "";
out_println(outputString.toString().replaceAll("\\s+$",""));
outputString = new StringBuilder();
}
}
if (!outputString.isEmpty()) {
out_println(outputString.replaceAll("\\s+$",""));
if (outputString.length() > 0) {
out_println(outputString.toString().replaceAll("\\s+$",""));
}
}
}
@ -740,11 +732,8 @@ class ClassData {
// Read the attributes
decodeAttrs(in, out);
break;
case ATT_ConstantValue:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_Exceptions:
case ATT_NestMembers:
int count = in.readUnsignedShort();
startArrayCmt(count, AttrName);
try {
@ -758,7 +747,7 @@ class ClassData {
break;
case ATT_LineNumberTable:
int ll_num = in.readUnsignedShort();
startArrayCmt(ll_num, AttrName);
startArrayCmt(ll_num, "line_number_table");
try {
for (int i = 0; i < ll_num; i++) {
out_println(in.readUnsignedShort() + " " +
@ -788,7 +777,7 @@ class ClassData {
break;
case ATT_InnerClasses:
int ic_num = in.readUnsignedShort();
startArrayCmt(ic_num, AttrName);
startArrayCmt(ic_num, "classes");
try {
for (int i = 0; i < ic_num; i++) {
out_println("#" + in.readUnsignedShort() + " #" +
@ -800,9 +789,6 @@ class ClassData {
out_end("}");
}
break;
case ATT_Signature:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_StackMap:
int e_num = in.readUnsignedShort();
startArrayCmt(e_num, "");
@ -887,9 +873,6 @@ class ClassData {
case ATT_EnclosingMethod:
decodeCPXAttrM(in, len, AttrName, out, 2);
break;
case ATT_SourceFile:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_AnnotationDefault:
decodeElementValue(in, out);
break;
@ -980,10 +963,6 @@ class ClassData {
out_end("}");
}
break;
// JEP 181: class file 55.0
case ATT_NestHost:
decodeCPXAttr(in, len, AttrName, out);
break;
// MethodParameters_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
@ -1026,13 +1005,48 @@ class ClassData {
out_end("}");
}
break;
case ATT_ConstantValue:
case ATT_Signature:
case ATT_SourceFile:
decodeCPXAttr(in, len, AttrName, out);
break;
// JEP 181 (Nest-based Access Control): class file 55.0
// NestHost_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 host_class_index;
// }
case ATT_NestHost:
decodeTypes(in, out, 1);
break;
// JEP 181 (Nest-based Access Control): class file 55.0
// NestMembers_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 number_of_classes;
// u2 classes[number_of_classes];
// }
case ATT_NestMembers:
// JEP 360 (Sealed types): class file 59.65535
// PermittedSubtypes_attribute {
// u2 attribute_name_index;
// u4 attribute_length;
// u2 permitted_subtypes_count;
// u2 classes[permitted_subtypes_count];
// }
case ATT_PermittedSubtypes:
int nsubtypes = in.readUnsignedShort();
startArrayCmt(nsubtypes, "classes");
try {
decodeTypes(in, out, nsubtypes);
} finally {
out_end("}");
}
break;
default:
printBytes(out, in, len);
if (AttrName == null) {
printBytes(out, in, len);
endingComment = "Attr(#" + name_cpx + ")";
} else {
// some kind of error?
printBytes(out, in, len);
}
}
@ -1168,13 +1182,13 @@ class ClassData {
}
private void decodeMembers(DataInputStream in, PrintWriter out, String groupName, String elementName) throws IOException {
int nfields = in.readUnsignedShort();
traceln(groupName + "=" + nfields);
startArrayCmt(nfields, groupName);
int count = in.readUnsignedShort();
traceln(groupName + "=" + count);
startArrayCmt(count, groupName);
try {
for (int i = 0; i < nfields; i++) {
for (int i = 0; i < count; i++) {
decodeInfo(in,out,elementName,true);
if (i + 1 < nfields) {
if (i + 1 < count) {
out_println(";");
}
}
@ -1205,7 +1219,7 @@ class ClassData {
entityType = "class";
}
if (!entityName.isEmpty() && (JcodTokens.keyword_token_ident(entityName) != JcodTokens.Token.IDENT || JcodTokens.constValue(entityName) != -1)) {
// Jcod can't parse a entityName matching a keyword or a constant value,
// JCod can't parse a entityName matching a keyword or a constant value,
// then use the filename instead:
out_begin(String.format("file \"%s.class\" {", entityName));
} else {
@ -1235,16 +1249,12 @@ class ClassData {
traceln(i18n.getString("jdec.trace.access_thisCpx_superCpx", access, this_cpx, super_cpx));
out.println();
// Read the interface names
// Read the interfaces
int numinterfaces = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.numinterfaces", numinterfaces));
startArrayCmt(numinterfaces, "Interfaces");
try {
for (int i = 0; i < numinterfaces; i++) {
int intrf_cpx = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.intrf", i, intrf_cpx));
out_println("#" + intrf_cpx + ";");
}
decodeTypes(in, out, numinterfaces);
} finally {
out_end("} // Interfaces\n");
}
@ -1267,6 +1277,20 @@ class ClassData {
}
} // end decodeClass()
private void decodeTypes(DataInputStream in, PrintWriter out, int count) throws IOException {
for (int i = 0; i < count; i++) {
int type_cpx = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.type", i, type_cpx));
out_print("#" + type_cpx + ";");
if (printDetails) {
String name = (String) cpool[(int)cpool[type_cpx]];
out.println(" // " + name + getStringPos());
} else {
out.println();
}
}
}
/* ====================================================== */
boolean DebugFlag = false;

View File

@ -1,4 +1,4 @@
# Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2014, 2020, 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
@ -37,5 +37,5 @@ jdec.trace.CP_len=CP len= {0}
jdec.trace.CP_entry=CP entry # {0} tag= {1}
jdec.trace.access_thisCpx_superCpx=access={0} this_cpx={1} super_cpx={2}
jdec.trace.numinterfaces=numinterfaces={0}
jdec.trace.intrf=\
\ intrf_cpx[{0}]={1}
jdec.trace.type=\
\ type_cpx[{0}]={1}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2018, 2020, 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;
/**
* Base class of the "classes[]" data of attributes
* <p>
* JEP 181 (Nest-based Access Control): class file 55.0
* NestMembers_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 number_of_classes;
* u2 classes[number_of_classes];
* }
* <p>
* JEP 360 (Sealed types): class file 59.65535
* PermittedSubtypes_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 permitted_subtypes_count;
* u2 classes[permitted_subtypes_count];
* }
* </p>
*/
public class ClassArrayData {
String name;
ClassData cls;
int[] classes;
private Options options = Options.OptionObject();
protected ClassArrayData(ClassData cls, String attrName) {
this.cls = cls;
this.name = attrName;
}
public ClassArrayData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError {
int number_of_classes = in.readUnsignedShort();
if (attribute_length != 2 + number_of_classes * 2) {
throw new ClassFormatError(name + "_attribute: Invalid attribute length");
}
classes = new int[number_of_classes];
for (int i = 0; i < number_of_classes; i++) {
classes[i] = in.readUnsignedShort();
}
return this;
}
public void print() {
String indexes = "";
String names = "";
boolean pr_cpx = options.contains(Options.PR.CPX);
cls.out.print(name + " ");
for (int i = 0; i < classes.length; i++) {
if (pr_cpx) {
indexes += (indexes.isEmpty() ? "" : ", ") + "#" + classes[i];
}
names += (names.isEmpty() ? "" : ", ") + cls.pool.StringValue(classes[i]);
}
if (pr_cpx) {
cls.out.print(indexes + "; // ");
}
cls.out.print(names);
if (pr_cpx) {
cls.out.println();
} else {
cls.out.println(";");
}
}
}

View File

@ -92,6 +92,9 @@ public class ClassData extends MemberData {
// The NestMembers of this class (since class file: 55.0)
protected NestMembersData nestMembers;
// The PermittedSubtypes of this class (JEP 360 (Sealed types): class file 59.65535)
protected PermittedSubtypesData permittedSubtypes;
// other parsing fields
protected PrintWriter out;
protected String pkgPrefix = "";
@ -215,6 +218,10 @@ public class ClassData extends MemberData {
case ATT_Record:
record = new RecordData(this).read(in);
break;
case ATT_PermittedSubtypes:
// Read PermittedSubtypes Attribute (JEP 360 (Sealed types): class file 59.65535)
permittedSubtypes = new PermittedSubtypesData(this).read(in, attrlen);
break;
default:
handled = false;
break;
@ -288,6 +295,7 @@ public class ClassData extends MemberData {
public void print() throws IOException {
int k, l;
String className = "";
String sourceName = "";
if( isModuleUnit() ) {
// Print the Annotations
printAnnotations(visibleAnnotations);
@ -407,20 +415,16 @@ printSugar:
out.println("{");
if ((options.contains(Options.PR.SRC)) && (source_cpx != 0)) {
String source_name = pool.getName(source_cpx);
out.println("\t// Compiled from " + source_name);
sourceName = String.format(" compiled from %s" +
"" , pool.getName(source_cpx));
try {
source = new TextLines(source_name);
source = new TextLines(sourceName);
} catch (IOException ignored) {}
}
// keep this new line for classes to pass huge test suite.
if(!isModuleUnit())
out.println();
// Print the constant pool
if (options.contains(Options.PR.CP)) {
pool.print(out);
out.println();
}
// Don't print fields, methods, inner classes and bootstrap methods if it is module-info entity
if ( !isModuleUnit() ) {
@ -446,6 +450,10 @@ printSugar:
record.print();
}
// Print PermittedSubtypes Attribute (JEP 360 (Sealed types): class file 59.65535)
if( permittedSubtypes != null) {
permittedSubtypes.print();
}
// Print the NestHost (since class file: 55.0)
if(nestHost != null) {
nestHost.print();
@ -470,7 +478,11 @@ printSugar:
}
out.println();
}
out.println("} // end Class " + className);
out.println("} // end Class " + className + sourceName);
} else {
// Print module attributes
moduleData.print();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2020, 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
@ -1049,7 +1049,7 @@ public class ConstantPool {
continue;
}
out.print("const #" + cpx + " = ");
out.print("\tconst #" + cpx + " = ");
if (cns == null) {
// do something
@ -1060,7 +1060,6 @@ public class ConstantPool {
cpx += cns.size();
}
}
out.println();
}
/**

View File

@ -66,7 +66,7 @@ class InnerClassData {
if (outer_class_info_index != 0) {
cls.out.print(" of #" + outer_class_info_index);
}
cls.out.print("; //");
cls.out.print("; // ");
}
if (inner_name_index != 0) {
cls.out.print(cls.pool.getName(inner_name_index) + "=");

View File

@ -336,6 +336,8 @@ public class MethodData extends MemberData {
if (code != null) {
code.print();
} else {
out.println();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@ -30,49 +30,20 @@ import java.io.IOException;
/**
* The NestMembers attribute data
* <p>
* since class file 55.0 (JEP 181)
* JEP 181 (Nest-based Access Control): class file 55.0
* NestMembers_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 number_of_classes;
* u2 classes[number_of_classes];
* }
*/
public class NestMembersData {
ClassData cls;
int[] classes;
private Options options = Options.OptionObject();
public class NestMembersData extends ClassArrayData {
public NestMembersData(ClassData cls) {
this.cls = cls;
super(cls, JasmTokens.Token.NESTMEMBERS.parsekey());
}
public NestMembersData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError {
int number_of_classes = in.readUnsignedShort();
if (attribute_length != 2 + number_of_classes * 2 ) {
throw new ClassFormatError("ATT_NestMembers: Invalid attribute length");
}
classes = new int[number_of_classes];
for (int i = 0; i < number_of_classes; i++) {
classes[i] = in.readUnsignedShort();
}
return this;
return (NestMembersData) super.read(in, attribute_length);
}
public void print() {
String indexes = "";
String names = "";
boolean pr_cpx = options.contains(Options.PR.CPX);
cls.out.print(JasmTokens.Token.NESTMEMBERS.parsekey() + " ");
for(int i = 0; i< classes.length; i++) {
if (pr_cpx) {
indexes += (indexes.isEmpty() ? "" : ", ") + "#" + classes[i];
}
names += (names.isEmpty() ? "" : ", ") + cls.pool.StringValue(classes[i]);
}
if (pr_cpx) {
cls.out.print(indexes + "; //");
}
cls.out.print(names);
if (pr_cpx) {
cls.out.println();
} else {
cls.out.println(";");
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2020, 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 java.io.DataInputStream;
import java.io.IOException;
/**
* The NestMembers attribute data
* <p>
* JEP 360 (Sealed types): class file 59.65535
* PermittedSubtypes_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 permitted_subtypes_count;
* u2 classes[permitted_subtypes_count];
* }
*/
public class PermittedSubtypesData extends ClassArrayData {
public PermittedSubtypesData(ClassData cls) {
super(cls, JasmTokens.Token.PERMITTEDSUBTYPES.parsekey());
}
public PermittedSubtypesData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError {
return (PermittedSubtypesData) super.read(in, attribute_length);
}
}