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

@ -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);
}
}
}

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 // JEP 359 - Record attribute since class file 58.65535
private RecordData recordData; private RecordData recordData;
// JEP 360 - PermittedSubtypes attribute since class file 59.65535
private PermittedTypesAttr permittedTypesAttr;
ModuleAttr moduleAttribute = null; ModuleAttr moduleAttribute = null;
Environment env; Environment env;
protected ConstantPool pool; protected ConstantPool pool;
@ -296,11 +299,17 @@ class ClassData extends MemberData {
nestHostAttr = new CPXAttr(this, AttrTag.ATT_NestHost.parsekey(), hostClass); 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"); 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() { public void endClass() {
sourceFileNameAttr = new CPXAttr(this, sourceFileNameAttr = new CPXAttr(this,
AttrTag.ATT_SourceFile.parsekey(), AttrTag.ATT_SourceFile.parsekey(),
@ -442,6 +451,9 @@ class ClassData extends MemberData {
attrs.add(nestHostAttr); attrs.add(nestHostAttr);
if(nestMembersAttributesExist()) if(nestMembersAttributesExist())
attrs.add(nestMembersAttr); attrs.add(nestMembersAttr);
// since class version 59.65535 (JEP 360)
if ( permittedSubtypesAttributesExist() )
attrs.add(permittedTypesAttr);
} }
return attrs; return attrs;
} }
@ -496,6 +508,8 @@ class ClassData extends MemberData {
public boolean nestMembersAttributesExist() { return nestMembersAttr != null; } public boolean nestMembersAttributesExist() { return nestMembersAttr != null; }
public boolean permittedSubtypesAttributesExist() { return permittedTypesAttr != null; }
public boolean recordAttributeExists() { return recordData != null; } public boolean recordAttributeExists() { return recordData != null; }
/** /**

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -308,10 +308,12 @@ public class JasmTokens {
// Declaration keywords // Declaration keywords
BOOTSTRAPMETHOD (172, "BOOTSTRAPMETHOD", "BootstrapMethod", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD), 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), 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), 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 //Module statements
REQUIRES (180, "REQUIRES", "requires", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD), REQUIRES (180, "REQUIRES", "requires", EnumSet.of(TokenType.DECLARATION, TokenType.JASM_IDENT, TokenType.MODULE_NAME ), KeywordType.KEYWORD),

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,33 +22,20 @@
*/ */
package org.openjdk.asmtools.jasm; package org.openjdk.asmtools.jasm;
import java.io.IOException;
import java.util.List; import java.util.List;
/** /**
* The NestMembers attribute data * The "classes[]" data of attributes
* <p> * JEP 181 (Nest-based Access Control): class file 55.0
* since class file 55.0 (JEP 181) * NestMembers_attribute {
* u2 attribute_name_index;
* u4 attribute_length;
* u2 number_of_classes;
* u2 classes[number_of_classes];
* }
*/ */
public class NestMembersAttr extends AttrData { public class NestMembersAttr extends ClassArrayAttr {
List<ConstantPool.ConstCell> nestMembers; public NestMembersAttr(ClassData cdata, List<ConstantPool.ConstCell> classes) {
super(Tables.AttrTag.ATT_NestMembers.parsekey(), cdata, classes);
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);
}
} }
} }

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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) // 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. // representing a class's or interface's method for which a method handle is to be created.
ConstType ctype = ConstType.CONSTANT_METHOD; 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; ctype = ConstType.CONSTANT_INTERFACEMETHOD;
} }
refCell = pool.FindCell(cpParser.parseConstValue(ctype)); refCell = pool.FindCell(cpParser.parseConstValue(ctype));
@ -561,28 +561,67 @@ class Parser extends ParseBase {
while (true) { while (true) {
nextmod = 0; nextmod = 0;
switch (scanner.token) { switch (scanner.token) {
case PUBLIC: nextmod = ACC_PUBLIC; break; case PUBLIC:
case PRIVATE: nextmod = ACC_PRIVATE; break; nextmod = ACC_PUBLIC;
case PROTECTED: nextmod = ACC_PROTECTED; break; break;
case STATIC: nextmod = ACC_STATIC; break; case PRIVATE:
case FINAL: nextmod = ACC_FINAL; break; nextmod = ACC_PRIVATE;
case SYNCHRONIZED: nextmod = ACC_SYNCHRONIZED; break; break;
case SUPER: nextmod = ACC_SUPER; break; case PROTECTED:
case VOLATILE: nextmod = ACC_VOLATILE; break; nextmod = ACC_PROTECTED;
case BRIDGE: nextmod = ACC_BRIDGE; break; break;
case TRANSIENT: nextmod = ACC_TRANSIENT; break; case STATIC:
case VARARGS: nextmod = ACC_VARARGS; break; nextmod = ACC_STATIC;
case NATIVE: nextmod = ACC_NATIVE; break; break;
case INTERFACE: nextmod = ACC_INTERFACE; break; case FINAL:
case ABSTRACT: nextmod = ACC_ABSTRACT; break; nextmod = ACC_FINAL;
case STRICT: nextmod = ACC_STRICT; break; break;
case ENUM: nextmod = ACC_ENUM; break; case SYNCHRONIZED:
case SYNTHETIC: nextmod = ACC_SYNTHETIC; break; 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: case ANNOTATION_ACCESS:
nextmod = ACC_ANNOTATION; break; nextmod = ACC_ANNOTATION;
break;
case DEPRECATED: nextmod = DEPRECATED_ATTRIBUTE; break; case DEPRECATED:
case MANDATED: nextmod = ACC_MANDATED; break; nextmod = DEPRECATED_ATTRIBUTE;
break;
case MANDATED:
nextmod = ACC_MANDATED;
break;
default: default:
return nextmod; 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 { private void parseClasses(Consumer<ArrayList<ConstCell>> classesConsumer)
ArrayList<ConstCell> nestMembers = new ArrayList<>(); throws Scanner.SyntaxError, IOException {
ArrayList<ConstCell> classes = new ArrayList<>();
// Parses in the form: // Parses in the form:
// NESTMEMBERS IDENT(, IDENT)*; // (NESTMEMBERS|PERMITTEDSUBTYPES)? IDENT(, IDENT)*;
debugStr(" [Parser.parseNestMembers]: <<<Begin>>>"); debugStr(" [Parser.parseClasses]: <<<Begin>>>");
while (true) { while (true) {
String className = prependPackage(parseIdent(), true); String className = prependPackage(parseIdent(), true);
nestMembers.add(pool.FindCellClassByName(className)); classes.add(pool.FindCellClassByName(className));
debugScan(" [Parser.parseNestMembers]: NestMembers: class " + className); debugScan(" [Parser.parseClasses]: class " + className);
if (scanner.token != Token.COMMA) { if (scanner.token != Token.COMMA) {
scanner.expect(Token.SEMICOLON); scanner.expect(Token.SEMICOLON);
cd.addNestMembers(nestMembers); classesConsumer.accept(classes);
return; return;
} }
scanner.scan(); 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 { private void parseRecord() throws Scanner.SyntaxError, IOException {
// Parses in the form: // Parses in the form:
@ -898,7 +938,7 @@ class Parser extends ParseBase {
// SIGNATURE = (CPINDEX | STRING) // SIGNATURE = (CPINDEX | STRING)
debugScan("[Parser.parseRecord]: Begin "); debugScan("[Parser.parseRecord]: Begin ");
RecordData rd = cd.setRecord(scanner.pos); RecordData rd = cd.setRecord(scanner.pos);
Component: Component:
while (true) { while (true) {
ConstCell nameCell, descCell, signatureCell = null; ConstCell nameCell, descCell, signatureCell = null;
nameCell = parseName(); nameCell = parseName();
@ -913,10 +953,10 @@ Component:
case SEMICOLON: case SEMICOLON:
return; // EOR return; // EOR
case ANNOTATION: case ANNOTATION:
rd.setAnnotations( annotParser.scanAnnotations()); rd.setAnnotations(annotParser.scanAnnotations());
break; break;
default: default:
if( signatureCell != null ) { if (signatureCell != null) {
env.error(scanner.pos, "warn.signature.repeated"); env.error(scanner.pos, "warn.signature.repeated");
} }
signatureCell = parseName(); signatureCell = parseName();
@ -1627,10 +1667,18 @@ Component:
throw new Scanner.SyntaxError(); throw new Scanner.SyntaxError();
} }
scanner.scan(); scanner.scan();
parseNestMembers(); parseClasses(list -> cd.addNestMembers(list));
break; break;
case RECORD: case PERMITTEDSUBTYPES: // JEP 360
if( cd.recordAttributeExists() ) { 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"); env.error(scanner.pos, "extra.record.attribute");
throw new Scanner.SyntaxError(); throw new Scanner.SyntaxError();
} }

@ -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);
}
}

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -227,7 +227,15 @@ public class Tables {
// u2 components_count; // u2 components_count;
// component_info components[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 Integer value;
private final String printval; private final String printval;

@ -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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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.undecl=Constant #{0} not declared.
err.const.redecl=Constant {0} redeclared. err.const.redecl=Constant {0} redeclared.
warn.const0.redecl=Re-declaration of Constant #0 cannot be written to the class file. 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.field.expected=Field, method, NestMembers, NestHost or Record declaration expected.
err.token.expected={0} expected. err.token.expected={0} expected.
err.identifier.expected=Identifier expected. err.identifier.expected=Identifier expected.
err.extra.nesthost.attribute=There may be at most one NestHost attribute. 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.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.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.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.name.expected=Name expected, got {0}.
err.module.name.expected=Module name expected, got {0}. err.module.name.expected=Module name expected, got {0}.
err.int.expected=Integer expected. 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.large=Value doesn't fit in {0}.
err.value.expected=Value expected. err.value.expected=Value expected.
err.wrong.mnemocode=Invalid mnemocode ({0}). 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.default.redecl=Default statement already declared in this table.
err.long.switchtable=Switchtable too long: > {0}. err.long.switchtable=Switchtable too long: > {0}.
err.io.exception=I/O error in {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.msig.malformed=Malformed method signature at char {0}. [err={1}]
err.no.classname=Class name not defined. err.no.classname=Class name not defined.
warn.msig.more255=Number of parameters too large ({0}>255). 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.illslot=Local variable at Illegal slot {0}.
#warn.invalid.modifier=This modifier is not allowed here
warn.repeated.modifier=Repeated modifier. warn.repeated.modifier=Repeated modifier.
warn.invalid.modifier.init=invalid modifier for <init> method \"{0}\". 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
@ -155,10 +150,7 @@ err.stackmap.repeated=stack_map redeclared.
err.version.expected=class file version expected err.version.expected=class file version expected
err.invalid.innerclass=Invalid declaration of Inner Class err.invalid.innerclass=Invalid declaration of Inner Class
err.invalid.bootstrapmethod=Invalid declaration of BootstrapMethod Entry 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.frametype.repeated=Frametype repeated
#err.module.expected=module expected
err.invalid.paramnum=Invalid Parameter Number: {0}. err.invalid.paramnum=Invalid Parameter Number: {0}.
err.duplicate.paramnum=Duplicate Parameter Number: {0}. err.duplicate.paramnum=Duplicate Parameter Number: {0}.
err.paramname.constnum.invaltype=ParameterName CPX at {0} is not a ConstantString. 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 # Compiler Errors
# #
# comperr.hashcode.err="CV hash:{0}"
comperr.constcell.nullvalset="Cell without value in setCell" comperr.constcell.nullvalset="Cell without value in setCell"
comperr.constcell.nullvalhash="Cell without value in cpoolHashByValue" comperr.constcell.nullvalhash="Cell without value in cpoolHashByValue"
comperr.constcell.invarg="Cell[{0}] has #{1}" comperr.constcell.invarg="Cell[{0}] has #{1}"

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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; int length = CPlen;
startArrayCmt(length, "Constant Pool"); startArrayCmt(length, "Constant Pool");
out_println("; // first element is empty"); out_println("; // first element is empty");
@ -273,7 +273,7 @@ class ClassData {
byte btag = types[i]; byte btag = types[i];
ConstType tg = tag(btag); ConstType tg = tag(btag);
int pos = cpe_pos[i]; int pos = cpe_pos[i];
String tagstr = ""; String tagstr;
String valstr; String valstr;
int v1; int v1;
long lv; long lv;
@ -359,14 +359,6 @@ class ClassData {
return " at " + toHex(countedin.getPos()); return " at " + toHex(countedin.getPos());
} }
private String getStringPosCond() {
if (printDetails) {
return getStringPos();
} else {
return "";
}
}
private String getCommentPosCond() { private String getCommentPosCond() {
if (printDetails) { if (printDetails) {
return " // " + getStringPos(); return " // " + getStringPos();
@ -384,16 +376,16 @@ class ClassData {
out_println("// invalid length of " + attrname + " attr: " + len + " (should be " + (expectedIndices * 2) + ") > "); out_println("// invalid length of " + attrname + " attr: " + len + " (should be " + (expectedIndices * 2) + ") > ");
printBytes(out, in, len); printBytes(out, in, len);
} else { } else {
String outputString = ""; StringBuilder outputString = new StringBuilder();
for (int k = 1; k <= expectedIndices; k++) { for (int k = 1; k <= expectedIndices; k++) {
outputString += ("#" + in.readUnsignedShort() + "; "); outputString.append("#").append(in.readUnsignedShort()).append("; ");
if (k % 16 == 0) { if (k % 16 == 0) {
out_println(outputString.replaceAll("\\s+$","")); out_println(outputString.toString().replaceAll("\\s+$",""));
outputString = ""; outputString = new StringBuilder();
} }
} }
if (!outputString.isEmpty()) { if (outputString.length() > 0) {
out_println(outputString.replaceAll("\\s+$","")); out_println(outputString.toString().replaceAll("\\s+$",""));
} }
} }
} }
@ -740,11 +732,8 @@ class ClassData {
// Read the attributes // Read the attributes
decodeAttrs(in, out); decodeAttrs(in, out);
break; break;
case ATT_ConstantValue:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_Exceptions: case ATT_Exceptions:
case ATT_NestMembers:
int count = in.readUnsignedShort(); int count = in.readUnsignedShort();
startArrayCmt(count, AttrName); startArrayCmt(count, AttrName);
try { try {
@ -758,7 +747,7 @@ class ClassData {
break; break;
case ATT_LineNumberTable: case ATT_LineNumberTable:
int ll_num = in.readUnsignedShort(); int ll_num = in.readUnsignedShort();
startArrayCmt(ll_num, AttrName); startArrayCmt(ll_num, "line_number_table");
try { try {
for (int i = 0; i < ll_num; i++) { for (int i = 0; i < ll_num; i++) {
out_println(in.readUnsignedShort() + " " + out_println(in.readUnsignedShort() + " " +
@ -788,7 +777,7 @@ class ClassData {
break; break;
case ATT_InnerClasses: case ATT_InnerClasses:
int ic_num = in.readUnsignedShort(); int ic_num = in.readUnsignedShort();
startArrayCmt(ic_num, AttrName); startArrayCmt(ic_num, "classes");
try { try {
for (int i = 0; i < ic_num; i++) { for (int i = 0; i < ic_num; i++) {
out_println("#" + in.readUnsignedShort() + " #" + out_println("#" + in.readUnsignedShort() + " #" +
@ -800,9 +789,6 @@ class ClassData {
out_end("}"); out_end("}");
} }
break; break;
case ATT_Signature:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_StackMap: case ATT_StackMap:
int e_num = in.readUnsignedShort(); int e_num = in.readUnsignedShort();
startArrayCmt(e_num, ""); startArrayCmt(e_num, "");
@ -887,9 +873,6 @@ class ClassData {
case ATT_EnclosingMethod: case ATT_EnclosingMethod:
decodeCPXAttrM(in, len, AttrName, out, 2); decodeCPXAttrM(in, len, AttrName, out, 2);
break; break;
case ATT_SourceFile:
decodeCPXAttr(in, len, AttrName, out);
break;
case ATT_AnnotationDefault: case ATT_AnnotationDefault:
decodeElementValue(in, out); decodeElementValue(in, out);
break; break;
@ -980,10 +963,6 @@ class ClassData {
out_end("}"); out_end("}");
} }
break; break;
// JEP 181: class file 55.0
case ATT_NestHost:
decodeCPXAttr(in, len, AttrName, out);
break;
// MethodParameters_attribute { // MethodParameters_attribute {
// u2 attribute_name_index; // u2 attribute_name_index;
// u4 attribute_length; // u4 attribute_length;
@ -1026,13 +1005,48 @@ class ClassData {
out_end("}"); out_end("}");
} }
break; 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: default:
printBytes(out, in, len);
if (AttrName == null) { if (AttrName == null) {
printBytes(out, in, len);
endingComment = "Attr(#" + name_cpx + ")"; 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 { private void decodeMembers(DataInputStream in, PrintWriter out, String groupName, String elementName) throws IOException {
int nfields = in.readUnsignedShort(); int count = in.readUnsignedShort();
traceln(groupName + "=" + nfields); traceln(groupName + "=" + count);
startArrayCmt(nfields, groupName); startArrayCmt(count, groupName);
try { try {
for (int i = 0; i < nfields; i++) { for (int i = 0; i < count; i++) {
decodeInfo(in,out,elementName,true); decodeInfo(in,out,elementName,true);
if (i + 1 < nfields) { if (i + 1 < count) {
out_println(";"); out_println(";");
} }
} }
@ -1205,7 +1219,7 @@ class ClassData {
entityType = "class"; entityType = "class";
} }
if (!entityName.isEmpty() && (JcodTokens.keyword_token_ident(entityName) != JcodTokens.Token.IDENT || JcodTokens.constValue(entityName) != -1)) { 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: // then use the filename instead:
out_begin(String.format("file \"%s.class\" {", entityName)); out_begin(String.format("file \"%s.class\" {", entityName));
} else { } else {
@ -1235,16 +1249,12 @@ class ClassData {
traceln(i18n.getString("jdec.trace.access_thisCpx_superCpx", access, this_cpx, super_cpx)); traceln(i18n.getString("jdec.trace.access_thisCpx_superCpx", access, this_cpx, super_cpx));
out.println(); out.println();
// Read the interface names // Read the interfaces
int numinterfaces = in.readUnsignedShort(); int numinterfaces = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.numinterfaces", numinterfaces)); traceln(i18n.getString("jdec.trace.numinterfaces", numinterfaces));
startArrayCmt(numinterfaces, "Interfaces"); startArrayCmt(numinterfaces, "Interfaces");
try { try {
for (int i = 0; i < numinterfaces; i++) { decodeTypes(in, out, numinterfaces);
int intrf_cpx = in.readUnsignedShort();
traceln(i18n.getString("jdec.trace.intrf", i, intrf_cpx));
out_println("#" + intrf_cpx + ";");
}
} finally { } finally {
out_end("} // Interfaces\n"); out_end("} // Interfaces\n");
} }
@ -1267,6 +1277,20 @@ class ClassData {
} }
} // end decodeClass() } // 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; boolean DebugFlag = false;

@ -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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # 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.CP_entry=CP entry # {0} tag= {1}
jdec.trace.access_thisCpx_superCpx=access={0} this_cpx={1} super_cpx={2} jdec.trace.access_thisCpx_superCpx=access={0} this_cpx={1} super_cpx={2}
jdec.trace.numinterfaces=numinterfaces={0} jdec.trace.numinterfaces=numinterfaces={0}
jdec.trace.intrf=\ jdec.trace.type=\
\ intrf_cpx[{0}]={1} \ type_cpx[{0}]={1}

@ -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(";");
}
}
}

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

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -1049,7 +1049,7 @@ public class ConstantPool {
continue; continue;
} }
out.print("const #" + cpx + " = "); out.print("\tconst #" + cpx + " = ");
if (cns == null) { if (cns == null) {
// do something // do something
@ -1060,7 +1060,6 @@ public class ConstantPool {
cpx += cns.size(); cpx += cns.size();
} }
} }
out.println();
} }
/** /**

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

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

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * The NestMembers attribute data
* <p> * <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 { public class NestMembersData extends ClassArrayData {
ClassData cls;
int[] classes;
private Options options = Options.OptionObject();
public NestMembersData(ClassData cls) { public NestMembersData(ClassData cls) {
this.cls = cls; super(cls, JasmTokens.Token.NESTMEMBERS.parsekey());
} }
public NestMembersData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError { public NestMembersData read(DataInputStream in, int attribute_length) throws IOException, ClassFormatError {
int number_of_classes = in.readUnsignedShort(); return (NestMembersData) super.read(in, attribute_length);
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;
} }
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(";");
}
}
} }

@ -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);
}
}