2014-12-18 21:56:02 +00:00
|
|
|
/*
|
2018-05-18 19:25:43 +00:00
|
|
|
* Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
|
2014-12-18 21:56:02 +00:00
|
|
|
* 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.asmutils.HexUtils;
|
2017-10-06 22:15:23 +00:00
|
|
|
import org.openjdk.asmtools.jasm.JasmTokens;
|
2014-12-18 21:56:02 +00:00
|
|
|
import org.openjdk.asmtools.jasm.Modifiers;
|
2016-03-02 21:00:55 +00:00
|
|
|
|
2014-12-18 21:56:02 +00:00
|
|
|
import java.io.*;
|
|
|
|
import java.util.ArrayList;
|
2017-11-07 23:28:57 +00:00
|
|
|
import java.util.Arrays;
|
2017-10-06 22:15:23 +00:00
|
|
|
import java.util.List;
|
2017-11-07 23:28:57 +00:00
|
|
|
import java.util.stream.Collectors;
|
2014-12-18 21:56:02 +00:00
|
|
|
|
2016-03-02 21:00:55 +00:00
|
|
|
import static org.openjdk.asmtools.jasm.RuntimeConstants.*;
|
|
|
|
import static org.openjdk.asmtools.jasm.Tables.*;
|
|
|
|
|
2014-12-18 21:56:02 +00:00
|
|
|
/**
|
|
|
|
* Central class data for of the Java Disassembler
|
|
|
|
*/
|
|
|
|
public class ClassData extends MemberData {
|
|
|
|
|
|
|
|
/*-------------------------------------------------------- */
|
2017-10-06 22:15:23 +00:00
|
|
|
/* ClassData Fields */
|
2014-12-18 21:56:02 +00:00
|
|
|
// -----------------------------
|
|
|
|
// Header Info
|
|
|
|
// -----------------------------
|
|
|
|
/**
|
|
|
|
* Version info
|
|
|
|
*/
|
2017-10-06 22:15:23 +00:00
|
|
|
protected int minor_version, major_version;
|
2014-12-18 21:56:02 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Constant Pool index to this class
|
|
|
|
*/
|
|
|
|
protected int this_cpx;
|
|
|
|
/**
|
|
|
|
* Constant Pool index to this classes parent (super)
|
|
|
|
*/
|
|
|
|
protected int super_cpx;
|
|
|
|
/**
|
|
|
|
* Constant Pool index to a file reference to the Java source
|
|
|
|
*/
|
|
|
|
protected int source_cpx = 0;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The Constant Pool
|
|
|
|
*/
|
|
|
|
protected ConstantPool pool;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The interfaces this class implements
|
|
|
|
*/
|
|
|
|
protected int[] interfaces;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The fields of this class
|
|
|
|
*/
|
|
|
|
protected ArrayList<FieldData> fields;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The methods of this class
|
|
|
|
*/
|
|
|
|
protected ArrayList<MethodData> methods;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The inner-classes of this class
|
|
|
|
*/
|
|
|
|
protected ArrayList<InnerClassData> innerClasses;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The bootstrapmethods this class implements
|
|
|
|
*/
|
|
|
|
protected ArrayList<BootstrapMethodData> bootstrapMethods;
|
|
|
|
|
2016-03-02 21:00:55 +00:00
|
|
|
/**
|
|
|
|
* The module this class file presents
|
|
|
|
*/
|
|
|
|
protected ModuleData moduleData;
|
|
|
|
|
2018-05-18 19:25:43 +00:00
|
|
|
/**
|
|
|
|
* The NestHost of this class (since class file: 55.0)
|
|
|
|
*/
|
|
|
|
protected NestHostData nestHost;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The NestMembers of this class (since class file: 55.0)
|
|
|
|
*/
|
|
|
|
protected NestMembersData nestMembers;
|
|
|
|
|
2014-12-18 21:56:02 +00:00
|
|
|
// 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) {
|
|
|
|
this.out = out;
|
|
|
|
init(this);
|
|
|
|
memberType = "ClassData";
|
|
|
|
TraceUtils.traceln("printOptions=" + options.toString());
|
|
|
|
pool = new ConstantPool(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*========================================================*/
|
|
|
|
/* Read Methods */
|
|
|
|
public void read(File in) throws IOException {
|
|
|
|
read(new DataInputStream(new FileInputStream(in)));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void read(String in) throws IOException {
|
|
|
|
read(new DataInputStream(new FileInputStream(in)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* readFields
|
|
|
|
*
|
|
|
|
* read and resolve the field data
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
protected void readFields(DataInputStream in) throws IOException {
|
|
|
|
int nfields = in.readUnsignedShort();
|
|
|
|
TraceUtils.traceln("nfields=" + nfields);
|
|
|
|
fields = new ArrayList<>(nfields);
|
|
|
|
for (int k = 0; k < nfields; k++) {
|
|
|
|
FieldData field = new FieldData(this);
|
|
|
|
TraceUtils.traceln(" FieldData: #" + k);
|
|
|
|
field.read(in);
|
|
|
|
fields.add(field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* readMethods
|
|
|
|
*
|
|
|
|
* read and resolve the method data
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
protected void readMethods(DataInputStream in) throws IOException {
|
|
|
|
int nmethods = in.readUnsignedShort();
|
|
|
|
TraceUtils.traceln("nmethods=" + nmethods);
|
|
|
|
methods = new ArrayList<>(nmethods);
|
|
|
|
for (int k = 0; k < nmethods; k++) {
|
|
|
|
MethodData method = new MethodData(this);
|
|
|
|
TraceUtils.traceln(" MethodData: #" + k);
|
|
|
|
method.read(in);
|
|
|
|
methods.add(method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* readInterfaces
|
|
|
|
*
|
|
|
|
* read and resolve the interface data
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
protected void readInterfaces(DataInputStream in) throws IOException {
|
|
|
|
// Read the interface names
|
|
|
|
int numinterfaces = in.readUnsignedShort();
|
|
|
|
TraceUtils.traceln("numinterfaces=" + numinterfaces);
|
|
|
|
interfaces = new int[numinterfaces];
|
|
|
|
for (int i = 0; i < numinterfaces; i++) {
|
|
|
|
int intrf_cpx = in.readShort();
|
|
|
|
TraceUtils.traceln(" intrf_cpx[" + i + "]=" + intrf_cpx);
|
|
|
|
interfaces[i] = intrf_cpx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* readAttributes
|
|
|
|
*
|
|
|
|
* read and resolve the attribute data
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
protected boolean handleAttributes(DataInputStream in, AttrTag attrtag, int attrlen) throws IOException {
|
|
|
|
// Read the Attributes
|
|
|
|
boolean handled = true;
|
|
|
|
switch (attrtag) {
|
|
|
|
case ATT_SourceFile:
|
|
|
|
// Read SourceFile Attr
|
|
|
|
if (attrlen != 2) {
|
2018-05-18 19:25:43 +00:00
|
|
|
throw new ClassFormatError("ATT_SourceFile: Invalid attribute length");
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
source_cpx = in.readUnsignedShort();
|
|
|
|
break;
|
|
|
|
case ATT_InnerClasses:
|
|
|
|
// Read InnerClasses Attr
|
|
|
|
int num1 = in.readUnsignedShort();
|
|
|
|
if (2 + num1 * 8 != attrlen) {
|
2018-05-18 19:25:43 +00:00
|
|
|
throw new ClassFormatError("ATT_InnerClasses: Invalid attribute length");
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
innerClasses = new ArrayList<>(num1);
|
|
|
|
for (int j = 0; j < num1; j++) {
|
|
|
|
InnerClassData innerClass = new InnerClassData(this);
|
|
|
|
innerClass.read(in);
|
|
|
|
innerClasses.add(innerClass);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ATT_BootstrapMethods:
|
|
|
|
// Read BootstrapMethods Attr
|
|
|
|
int num2 = in.readUnsignedShort();
|
|
|
|
bootstrapMethods = new ArrayList<>(num2);
|
|
|
|
for (int j = 0; j < num2; j++) {
|
|
|
|
BootstrapMethodData bsmData = new BootstrapMethodData(this);
|
|
|
|
bsmData.read(in);
|
|
|
|
bootstrapMethods.add(bsmData);
|
|
|
|
}
|
|
|
|
break;
|
2016-03-02 21:00:55 +00:00
|
|
|
case ATT_Module:
|
|
|
|
// Read Module Attribute
|
|
|
|
moduleData = new ModuleData(this);
|
|
|
|
moduleData.read(in);
|
|
|
|
break;
|
2018-05-18 19:25:43 +00:00
|
|
|
case ATT_NestHost:
|
|
|
|
// Read NestHost Attribute (since class file: 55.0)
|
|
|
|
nestHost = new NestHostData(this).read(in, attrlen);
|
|
|
|
break;
|
|
|
|
case ATT_NestMembers:
|
|
|
|
// Read NestMembers Attribute (since class file: 55.0)
|
|
|
|
nestMembers = new NestMembersData(this).read(in, attrlen);
|
|
|
|
break;
|
2014-12-18 21:56:02 +00:00
|
|
|
default:
|
|
|
|
handled = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* read
|
|
|
|
*
|
|
|
|
* 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));
|
|
|
|
}
|
|
|
|
minor_version = in.readShort();
|
|
|
|
major_version = in.readShort();
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
// 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("");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*========================================================*/
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* getSrcLine
|
|
|
|
*
|
|
|
|
* read and resolve the attribute data
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public String getSrcLine(int lnum) {
|
|
|
|
if (source == null) {
|
|
|
|
return null; // impossible call
|
|
|
|
}
|
|
|
|
String line;
|
|
|
|
try {
|
|
|
|
line = source.getLine(lnum);
|
|
|
|
} catch (ArrayIndexOutOfBoundsException e) {
|
|
|
|
line = "Line number " + lnum + " is out of bounds";
|
|
|
|
}
|
|
|
|
return line;
|
|
|
|
}
|
|
|
|
|
2017-10-06 22:15:23 +00:00
|
|
|
private <T extends AnnotationData> void printAnnotations(List<T> annotations) {
|
|
|
|
if (annotations != null) {
|
|
|
|
for (T ad : annotations) {
|
|
|
|
ad.print(out, initialTab);
|
|
|
|
out.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-18 21:56:02 +00:00
|
|
|
public void print() throws IOException {
|
|
|
|
int k, l;
|
2017-10-06 22:15:23 +00:00
|
|
|
String className = "";
|
|
|
|
if( isModuleUnit() ) {
|
2014-12-18 21:56:02 +00:00
|
|
|
// Print the Annotations
|
2017-10-06 22:15:23 +00:00
|
|
|
printAnnotations(visibleAnnotations);
|
|
|
|
printAnnotations(invisibleAnnotations);
|
|
|
|
} else {
|
|
|
|
className = pool.getClassName(this_cpx);
|
|
|
|
pkgPrefixLen = className.lastIndexOf("/") + 1;
|
|
|
|
// Write the header
|
|
|
|
// package-info compilation unit
|
|
|
|
if (className.endsWith("package-info")) {
|
|
|
|
// Print the Annotations
|
|
|
|
printAnnotations(visibleAnnotations);
|
|
|
|
printAnnotations(invisibleAnnotations);
|
|
|
|
printAnnotations(visibleTypeAnnotations);
|
|
|
|
printAnnotations(invisibleTypeAnnotations);
|
|
|
|
if (pkgPrefixLen != 0) {
|
|
|
|
pkgPrefix = className.substring(0, pkgPrefixLen);
|
|
|
|
out.print("package " + pkgPrefix.substring(0, pkgPrefixLen - 1) + " ");
|
|
|
|
out.print("version " + major_version + ":" + minor_version + ";");
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
out.println();
|
2017-10-06 22:15:23 +00:00
|
|
|
return;
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
2016-03-02 21:00:55 +00:00
|
|
|
if (pkgPrefixLen != 0) {
|
|
|
|
pkgPrefix = className.substring(0, pkgPrefixLen);
|
|
|
|
out.println("package " + pkgPrefix.substring(0, pkgPrefixLen - 1) + ";");
|
|
|
|
className = pool.getShortClassName(this_cpx, pkgPrefix);
|
|
|
|
}
|
|
|
|
out.println();
|
|
|
|
// Print the Annotations
|
2017-10-06 22:15:23 +00:00
|
|
|
printAnnotations(visibleAnnotations);
|
|
|
|
printAnnotations(invisibleAnnotations);
|
|
|
|
printAnnotations(visibleTypeAnnotations);
|
|
|
|
printAnnotations(invisibleTypeAnnotations);
|
2016-03-02 21:00:55 +00:00
|
|
|
if ((access & ACC_SUPER) != 0) {
|
|
|
|
out.print("super ");
|
|
|
|
access = access & ~ACC_SUPER;
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
2017-10-06 22:15:23 +00:00
|
|
|
// see if we are going to print: abstract interface class
|
2014-12-18 21:56:02 +00:00
|
|
|
// then replace it with just: interface
|
|
|
|
printHeader:
|
|
|
|
{
|
|
|
|
printSugar:
|
|
|
|
{
|
|
|
|
if ((access & ACC_ABSTRACT) == 0) {
|
|
|
|
break printSugar;
|
|
|
|
}
|
|
|
|
if ((access & ACC_INTERFACE) == 0) {
|
|
|
|
break printSugar;
|
|
|
|
}
|
|
|
|
if (options.contains(Options.PR.CPX)) {
|
|
|
|
break printSugar;
|
|
|
|
}
|
|
|
|
if (this_cpx == 0) {
|
|
|
|
break printSugar;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure the this_class is a valid class ref
|
|
|
|
ConstantPool.Constant this_const = pool.getConst(this_cpx);
|
|
|
|
if (this_const == null || this_const.tag != ConstantPool.TAG.CONSTANT_CLASS) {
|
|
|
|
break printSugar;
|
|
|
|
}
|
|
|
|
|
|
|
|
// all conditions met, print syntactic sugar:
|
|
|
|
out.print(Modifiers.accessString(access & ~ACC_ABSTRACT, CF_Context.CTX_CLASS));
|
|
|
|
if (isSynthetic) {
|
|
|
|
out.print("synthetic ");
|
|
|
|
}
|
|
|
|
if (isDeprecated) {
|
|
|
|
out.print("deprecated ");
|
|
|
|
}
|
|
|
|
out.print(" " + pool.getShortClassName(this_cpx, pkgPrefix));
|
|
|
|
break printHeader;
|
|
|
|
}
|
|
|
|
|
2017-10-06 22:15:23 +00:00
|
|
|
if(isModuleUnit()) {
|
|
|
|
out.print(moduleData.getModuleHeader());
|
|
|
|
} else {
|
|
|
|
// not all conditions met, print header in ordinary way:
|
|
|
|
out.print(Modifiers.accessString(access, CF_Context.CTX_CLASS));
|
|
|
|
if (isSynthetic) {
|
|
|
|
out.print("synthetic ");
|
|
|
|
}
|
|
|
|
if (isDeprecated) {
|
|
|
|
out.print("deprecated ");
|
|
|
|
}
|
|
|
|
if (options.contains(Options.PR.CPX)) {
|
|
|
|
out.print("\t#" + this_cpx + "; //");
|
|
|
|
}
|
|
|
|
pool.PrintConstant(out, this_cpx);
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
out.println();
|
2017-10-06 22:15:23 +00:00
|
|
|
if(!isModuleUnit()) {
|
2016-03-02 21:00:55 +00:00
|
|
|
if (!pool.getClassName(super_cpx).equals("java/lang/Object")) {
|
|
|
|
out.print("\textends ");
|
|
|
|
pool.printlnClassId(out, super_cpx);
|
|
|
|
out.println();
|
|
|
|
}
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
l = interfaces.length;
|
|
|
|
|
|
|
|
if (l > 0) {
|
|
|
|
for (k = 0; k < l; k++) {
|
|
|
|
if (k == 0) {
|
|
|
|
out.print("\timplements ");
|
|
|
|
} else {
|
|
|
|
out.print("\t\t ");
|
|
|
|
}
|
|
|
|
boolean printComma = (l > 1 && k < (l - 1));
|
|
|
|
pool.printlnClassId(out, interfaces[k], printComma);
|
|
|
|
out.println();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out.println("\tversion " + major_version + ":" + minor_version);
|
|
|
|
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);
|
|
|
|
try {
|
|
|
|
source = new TextLines(source_name);
|
2017-10-06 22:15:23 +00:00
|
|
|
} catch (IOException ignored) {}
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
2016-03-02 21:00:55 +00:00
|
|
|
// keep this new line for classes to pass huge test suite.
|
2017-10-06 22:15:23 +00:00
|
|
|
if(!isModuleUnit())
|
2016-03-02 21:00:55 +00:00
|
|
|
out.println();
|
2014-12-18 21:56:02 +00:00
|
|
|
|
|
|
|
// Print the constant pool
|
|
|
|
if (options.contains(Options.PR.CP)) {
|
|
|
|
pool.print(out);
|
|
|
|
out.println();
|
|
|
|
}
|
2017-10-06 22:15:23 +00:00
|
|
|
// Don't print fields, methods, inner classes and bootstrap methods if it is module-info entity
|
|
|
|
if ( !isModuleUnit() ) {
|
2014-12-18 21:56:02 +00:00
|
|
|
|
2017-10-06 22:15:23 +00:00
|
|
|
// Print the fields
|
|
|
|
if (fields != null && !fields.isEmpty()) {
|
|
|
|
for (FieldData curf : fields) {
|
|
|
|
curf.print();
|
|
|
|
}
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
|
|
|
|
2017-10-06 22:15:23 +00:00
|
|
|
// Print the methods
|
|
|
|
if (methods != null && !methods.isEmpty()) {
|
|
|
|
for (MethodData curm : methods) {
|
|
|
|
boolean skipBlankLine = false;
|
|
|
|
curm.print(skipBlankLine);
|
|
|
|
}
|
|
|
|
out.println();
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
2018-05-18 19:25:43 +00:00
|
|
|
// Print the NestHost (since class file: 55.0)
|
|
|
|
if(nestHost != null) {
|
|
|
|
nestHost.print();
|
|
|
|
}
|
|
|
|
// Print the NestMembers (since class file: 55.0)
|
|
|
|
if( nestMembers != null) {
|
|
|
|
nestMembers.print();
|
|
|
|
}
|
2017-10-06 22:15:23 +00:00
|
|
|
// Print the inner classes
|
|
|
|
if (innerClasses != null && !innerClasses.isEmpty()) {
|
|
|
|
for (InnerClassData icd : innerClasses) {
|
|
|
|
icd.print();
|
|
|
|
}
|
|
|
|
out.println();
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
2017-10-06 22:15:23 +00:00
|
|
|
// Print the BootstrapMethods
|
|
|
|
//
|
|
|
|
// Only print these if printing extended constants
|
|
|
|
if ((options.contains(Options.PR.CPX)) && bootstrapMethods != null && !bootstrapMethods.isEmpty()) {
|
|
|
|
for (BootstrapMethodData bsmdd : bootstrapMethods) {
|
|
|
|
bsmdd.print();
|
|
|
|
}
|
|
|
|
out.println();
|
2014-12-18 21:56:02 +00:00
|
|
|
}
|
2016-03-02 21:00:55 +00:00
|
|
|
out.println("} // end Class " + className);
|
2017-10-06 22:15:23 +00:00
|
|
|
} else {
|
|
|
|
// Print module attributes
|
|
|
|
moduleData.print();
|
|
|
|
out.print("} // end Module ");
|
|
|
|
out.print( moduleData.getModuleName());
|
|
|
|
if(moduleData.getModuleVersion() != null)
|
|
|
|
out.print(" @" + moduleData.getModuleVersion());
|
|
|
|
out.println();
|
2016-03-02 21:00:55 +00:00
|
|
|
}
|
2017-11-07 23:28:57 +00:00
|
|
|
|
|
|
|
List<IOException> issues = getIssues();
|
|
|
|
if( !issues.isEmpty() ) {
|
|
|
|
|
|
|
|
throw issues.get(0);
|
|
|
|
}
|
2014-12-18 21:56:02 +00:00
|
|
|
} // end ClassData.print()
|
|
|
|
|
2017-10-06 22:15:23 +00:00
|
|
|
// Gets the type of processed binary
|
|
|
|
private boolean isModuleUnit() {
|
|
|
|
return moduleData != null;
|
|
|
|
}
|
2017-11-07 23:28:57 +00:00
|
|
|
|
|
|
|
private List<IOException> getIssues() {
|
2018-05-18 19:25:43 +00:00
|
|
|
return this.pool.pool.stream().
|
|
|
|
filter(c->c!=null).
|
|
|
|
filter(c->c.getIssue() != null).
|
|
|
|
map(c->c.getIssue()).
|
|
|
|
collect(Collectors.toList());
|
2017-11-07 23:28:57 +00:00
|
|
|
}
|
|
|
|
|
2014-12-18 21:56:02 +00:00
|
|
|
}// end class ClassData
|
|
|
|
|