6824493: experimental support for additional info for instructions
Reviewed-by: mcimadamore
This commit is contained in:
parent
f05e74203e
commit
72b623769a
@ -107,6 +107,8 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public abstract int getOffsetDelta();
|
||||
|
||||
public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
|
||||
|
||||
public final int frame_type;
|
||||
@ -130,6 +132,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
public <R, D> R accept(Visitor<R, D> visitor, D data) {
|
||||
return visitor.visit_same_frame(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return frame_type;
|
||||
}
|
||||
}
|
||||
|
||||
public static class same_locals_1_stack_item_frame extends stack_map_frame {
|
||||
@ -149,6 +155,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_same_locals_1_stack_item_frame(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return frame_type - 64;
|
||||
}
|
||||
|
||||
public final verification_type_info[] stack;
|
||||
}
|
||||
|
||||
@ -170,6 +180,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_same_locals_1_stack_item_frame_extended(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return offset_delta;
|
||||
}
|
||||
|
||||
public final int offset_delta;
|
||||
public final verification_type_info[] stack;
|
||||
}
|
||||
@ -189,6 +203,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_chop_frame(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return offset_delta;
|
||||
}
|
||||
|
||||
public final int offset_delta;
|
||||
}
|
||||
|
||||
@ -207,6 +225,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_same_frame_extended(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return offset_delta;
|
||||
}
|
||||
|
||||
public final int offset_delta;
|
||||
}
|
||||
|
||||
@ -232,6 +254,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_append_frame(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return offset_delta;
|
||||
}
|
||||
|
||||
public final int offset_delta;
|
||||
public final verification_type_info[] locals;
|
||||
}
|
||||
@ -266,6 +292,10 @@ public class StackMapTable_attribute extends Attribute {
|
||||
return visitor.visit_full_frame(this, data);
|
||||
}
|
||||
|
||||
public int getOffsetDelta() {
|
||||
return offset_delta;
|
||||
}
|
||||
|
||||
public final int offset_delta;
|
||||
public final int number_of_locals;
|
||||
public final verification_type_info[] locals;
|
||||
@ -308,7 +338,7 @@ public class StackMapTable_attribute extends Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
verification_type_info(int tag) {
|
||||
protected verification_type_info(int tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
|
@ -44,6 +44,9 @@ public class BasicWriter {
|
||||
protected BasicWriter(Context context) {
|
||||
lineWriter = LineWriter.instance(context);
|
||||
out = context.get(PrintWriter.class);
|
||||
messages = context.get(Messages.class);
|
||||
if (messages == null)
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
protected void print(String s) {
|
||||
@ -88,8 +91,26 @@ public class BasicWriter {
|
||||
return "???";
|
||||
}
|
||||
|
||||
protected String space(int w) {
|
||||
if (w < spaces.length && spaces[w] != null)
|
||||
return spaces[w];
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < w; i++)
|
||||
sb.append(" ");
|
||||
|
||||
String s = sb.toString();
|
||||
if (w < spaces.length)
|
||||
spaces[w] = s;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private String[] spaces = new String[80];
|
||||
|
||||
private LineWriter lineWriter;
|
||||
private PrintWriter out;
|
||||
protected Messages messages;
|
||||
|
||||
private static class LineWriter {
|
||||
static LineWriter instance(Context context) {
|
||||
|
@ -26,7 +26,9 @@
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.net.URI;
|
||||
import java.text.DateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
@ -47,8 +49,6 @@ import com.sun.tools.classfile.Signature_attribute;
|
||||
import com.sun.tools.classfile.SourceFile_attribute;
|
||||
import com.sun.tools.classfile.Type;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import static com.sun.tools.classfile.AccessFlags.*;
|
||||
|
||||
/*
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
@ -33,9 +36,6 @@ import com.sun.tools.classfile.DescriptorException;
|
||||
import com.sun.tools.classfile.Instruction;
|
||||
import com.sun.tools.classfile.Instruction.TypeKind;
|
||||
import com.sun.tools.classfile.Method;
|
||||
import com.sun.tools.classfile.Opcode;
|
||||
|
||||
//import static com.sun.tools.classfile.OpCodes.*;
|
||||
|
||||
/*
|
||||
* Write the contents of a Code attribute.
|
||||
@ -59,6 +59,12 @@ class CodeWriter extends BasicWriter {
|
||||
attrWriter = AttributeWriter.instance(context);
|
||||
classWriter = ClassWriter.instance(context);
|
||||
constantWriter = ConstantWriter.instance(context);
|
||||
sourceWriter = SourceWriter.instance(context);
|
||||
tryBlockWriter = TryBlockWriter.instance(context);
|
||||
stackMapWriter = StackMapWriter.instance(context);
|
||||
localVariableTableWriter = LocalVariableTableWriter.instance(context);
|
||||
localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
|
||||
options = Options.instance(context);
|
||||
}
|
||||
|
||||
void write(Code_attribute attr, ConstantPool constant_pool) {
|
||||
@ -90,14 +96,21 @@ class CodeWriter extends BasicWriter {
|
||||
}
|
||||
|
||||
public void writeInstrs(Code_attribute attr) {
|
||||
List<InstructionDetailWriter> detailWriters = getDetailWriters(attr);
|
||||
|
||||
for (Instruction instr: attr.getInstructions()) {
|
||||
try {
|
||||
for (InstructionDetailWriter w: detailWriters)
|
||||
w.writeDetails(instr);
|
||||
writeInstr(instr);
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
println(report("error at or after byte " + instr.getPC()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (InstructionDetailWriter w: detailWriters)
|
||||
w.flush();
|
||||
}
|
||||
|
||||
public void writeInstr(Instruction instr) {
|
||||
@ -211,11 +224,45 @@ class CodeWriter extends BasicWriter {
|
||||
print(s);
|
||||
}
|
||||
|
||||
private static int align(int n) {
|
||||
return (n + 3) & ~3;
|
||||
private List<InstructionDetailWriter> getDetailWriters(Code_attribute attr) {
|
||||
List<InstructionDetailWriter> detailWriters =
|
||||
new ArrayList<InstructionDetailWriter>();
|
||||
if (options.details.contains(InstructionDetailWriter.Kind.SOURCE)) {
|
||||
sourceWriter.reset(classWriter.getClassFile(), attr);
|
||||
detailWriters.add(sourceWriter);
|
||||
}
|
||||
|
||||
if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VARS)) {
|
||||
localVariableTableWriter.reset(attr);
|
||||
detailWriters.add(localVariableTableWriter);
|
||||
}
|
||||
|
||||
if (options.details.contains(InstructionDetailWriter.Kind.LOCAL_VAR_TYPES)) {
|
||||
localVariableTypeTableWriter.reset(attr);
|
||||
detailWriters.add(localVariableTypeTableWriter);
|
||||
}
|
||||
|
||||
if (options.details.contains(InstructionDetailWriter.Kind.STACKMAPS)) {
|
||||
stackMapWriter.reset(attr);
|
||||
stackMapWriter.writeInitialDetails();
|
||||
detailWriters.add(stackMapWriter);
|
||||
}
|
||||
|
||||
if (options.details.contains(InstructionDetailWriter.Kind.TRY_BLOCKS)) {
|
||||
tryBlockWriter.reset(attr);
|
||||
detailWriters.add(tryBlockWriter);
|
||||
}
|
||||
|
||||
return detailWriters;
|
||||
}
|
||||
|
||||
private AttributeWriter attrWriter;
|
||||
private ClassWriter classWriter;
|
||||
private ConstantWriter constantWriter;
|
||||
private LocalVariableTableWriter localVariableTableWriter;
|
||||
private LocalVariableTypeTableWriter localVariableTypeTableWriter;
|
||||
private SourceWriter sourceWriter;
|
||||
private StackMapWriter stackMapWriter;
|
||||
private TryBlockWriter tryBlockWriter;
|
||||
private Options options;
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import com.sun.tools.classfile.Instruction;
|
||||
|
||||
|
||||
/*
|
||||
* Write additional details for an instruction.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public abstract class InstructionDetailWriter extends BasicWriter {
|
||||
public enum Kind {
|
||||
LOCAL_VARS("localVariables"),
|
||||
LOCAL_VAR_TYPES("localVariableTypes"),
|
||||
SOURCE("source"),
|
||||
STACKMAPS("stackMaps"),
|
||||
TRY_BLOCKS("tryBlocks");
|
||||
Kind(String option) {
|
||||
this.option = option;
|
||||
}
|
||||
final String option;
|
||||
}
|
||||
InstructionDetailWriter(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
abstract void writeDetails(Instruction instr);
|
||||
void flush() { }
|
||||
}
|
@ -39,6 +39,7 @@ import java.security.MessageDigest;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -65,7 +66,7 @@ import com.sun.tools.classfile.*;
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class JavapTask implements DisassemblerTool.DisassemblerTask {
|
||||
public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
|
||||
public class BadArgs extends Exception {
|
||||
static final long serialVersionUID = 8765093759964640721L;
|
||||
BadArgs(String key, Object... args) {
|
||||
@ -241,6 +242,56 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask {
|
||||
}
|
||||
},
|
||||
|
||||
new Option(false, "-XDdetails") {
|
||||
void process(JavapTask task, String opt, String arg) {
|
||||
task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
new Option(false, "-XDdetails:") {
|
||||
@Override
|
||||
boolean matches(String opt) {
|
||||
int sep = opt.indexOf(":");
|
||||
return sep != -1 && super.matches(opt.substring(0, sep + 1));
|
||||
}
|
||||
|
||||
void process(JavapTask task, String opt, String arg) throws BadArgs {
|
||||
int sep = opt.indexOf(":");
|
||||
for (String v: opt.substring(sep + 1).split("[,: ]+")) {
|
||||
if (!handleArg(task, v))
|
||||
throw task.new BadArgs("err.invalid.arg.for.option", v);
|
||||
}
|
||||
}
|
||||
|
||||
boolean handleArg(JavapTask task, String arg) {
|
||||
if (arg.length() == 0)
|
||||
return true;
|
||||
|
||||
if (arg.equals("all")) {
|
||||
task.options.details = EnumSet.allOf(InstructionDetailWriter.Kind.class);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean on = true;
|
||||
if (arg.startsWith("-")) {
|
||||
on = false;
|
||||
arg = arg.substring(1);
|
||||
}
|
||||
|
||||
for (InstructionDetailWriter.Kind k: InstructionDetailWriter.Kind.values()) {
|
||||
if (arg.equalsIgnoreCase(k.option)) {
|
||||
if (on)
|
||||
task.options.details.add(k);
|
||||
else
|
||||
task.options.details.remove(k);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
new Option(false, "-constants") {
|
||||
void process(JavapTask task, String opt, String arg) {
|
||||
task.options.showConstants = true;
|
||||
@ -251,6 +302,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask {
|
||||
|
||||
JavapTask() {
|
||||
context = new Context();
|
||||
context.put(Messages.class, this);
|
||||
options = Options.instance(context);
|
||||
}
|
||||
|
||||
@ -469,6 +521,8 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask {
|
||||
|
||||
context.put(PrintWriter.class, log);
|
||||
ClassWriter classWriter = ClassWriter.instance(context);
|
||||
SourceWriter sourceWriter = SourceWriter.instance(context);
|
||||
sourceWriter.setFileManager(fileManager);
|
||||
|
||||
boolean ok = true;
|
||||
|
||||
@ -651,11 +705,11 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask {
|
||||
|
||||
}
|
||||
|
||||
private String getMessage(String key, Object... args) {
|
||||
public String getMessage(String key, Object... args) {
|
||||
return getMessage(task_locale, key, args);
|
||||
}
|
||||
|
||||
private String getMessage(Locale locale, String key, Object... args) {
|
||||
public String getMessage(Locale locale, String key, Object... args) {
|
||||
if (bundles == null) {
|
||||
// could make this a HashMap<Locale,SoftReference<ResourceBundle>>
|
||||
// and for efficiency, keep a hard reference to the bundle for the task
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2007-2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Access to javap messages.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public interface Messages {
|
||||
String getMessage(String key, Object... args);
|
||||
|
||||
String getMessage(Locale locale, String key, Object... args);
|
||||
}
|
@ -25,8 +25,10 @@
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
|
||||
/*
|
||||
@ -77,6 +79,7 @@ public class Options {
|
||||
public boolean showLineAndLocalVariableTables;
|
||||
public int showAccess;
|
||||
public Set<String> accessOptions = new HashSet<String>();
|
||||
public Set<InstructionDetailWriter.Kind> details = EnumSet.noneOf(InstructionDetailWriter.Kind.class);
|
||||
public boolean showDisassembled;
|
||||
public boolean showInternalSignatures;
|
||||
public boolean showAllAttrs;
|
||||
|
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.SortedMap;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import javax.tools.JavaFileManager;
|
||||
import javax.tools.JavaFileManager.Location;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.StandardLocation;
|
||||
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Instruction;
|
||||
import com.sun.tools.classfile.LineNumberTable_attribute;
|
||||
import com.sun.tools.classfile.SourceFile_attribute;
|
||||
|
||||
|
||||
/**
|
||||
* Annotate instructions with source code.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class SourceWriter extends InstructionDetailWriter {
|
||||
static SourceWriter instance(Context context) {
|
||||
SourceWriter instance = context.get(SourceWriter.class);
|
||||
if (instance == null)
|
||||
instance = new SourceWriter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected SourceWriter(Context context) {
|
||||
super(context);
|
||||
context.put(SourceWriter.class, this);
|
||||
}
|
||||
|
||||
void setFileManager(JavaFileManager fileManager) {
|
||||
this.fileManager = fileManager;
|
||||
}
|
||||
|
||||
public void reset(ClassFile cf, Code_attribute attr) {
|
||||
setSource(cf);
|
||||
setLineMap(attr);
|
||||
}
|
||||
|
||||
public void writeDetails(Instruction instr) {
|
||||
String indent = space(40); // could get from Options?
|
||||
Set<Integer> lines = lineMap.get(instr.getPC());
|
||||
if (lines != null) {
|
||||
for (int line: lines) {
|
||||
print(indent);
|
||||
print(String.format(" %4d ", line));
|
||||
if (line < sourceLines.length)
|
||||
print(sourceLines[line]);
|
||||
println();
|
||||
int nextLine = nextLine(line);
|
||||
for (int i = line + 1; i < nextLine; i++) {
|
||||
print(indent);
|
||||
print(String.format("(%4d)", i));
|
||||
if (i < sourceLines.length)
|
||||
print(sourceLines[i]);
|
||||
println();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setLineMap(Code_attribute attr) {
|
||||
SortedMap<Integer, SortedSet<Integer>> map =
|
||||
new TreeMap<Integer, SortedSet<Integer>>();
|
||||
SortedSet<Integer> allLines = new TreeSet<Integer>();
|
||||
for (Attribute a: attr.attributes) {
|
||||
if (a instanceof LineNumberTable_attribute) {
|
||||
LineNumberTable_attribute t = (LineNumberTable_attribute) a;
|
||||
for (LineNumberTable_attribute.Entry e: t.line_number_table) {
|
||||
int start_pc = e.start_pc;
|
||||
int line = e.line_number;
|
||||
SortedSet<Integer> pcLines = map.get(start_pc);
|
||||
if (pcLines == null) {
|
||||
pcLines = new TreeSet<Integer>();
|
||||
map.put(start_pc, pcLines);
|
||||
}
|
||||
pcLines.add(line);
|
||||
allLines.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
lineMap = map;
|
||||
lineList = new ArrayList<Integer>(allLines);
|
||||
}
|
||||
|
||||
private void setSource(ClassFile cf) {
|
||||
if (cf != classFile) {
|
||||
classFile = cf;
|
||||
sourceLines = splitLines(readSource(cf));
|
||||
}
|
||||
}
|
||||
|
||||
private String readSource(ClassFile cf) {
|
||||
Location location;
|
||||
if (fileManager.hasLocation((StandardLocation.SOURCE_PATH)))
|
||||
location = StandardLocation.SOURCE_PATH;
|
||||
else
|
||||
location = StandardLocation.CLASS_PATH;
|
||||
|
||||
// Guess the source file for a class from the package name for this
|
||||
// class and the base of the source file. This avoids having to read
|
||||
// additional classes to determine the outmost class from any
|
||||
// InnerClasses and EnclosingMethod attributes.
|
||||
try {
|
||||
String className = cf.getName();
|
||||
SourceFile_attribute sf =
|
||||
(SourceFile_attribute) cf.attributes.get(Attribute.SourceFile);
|
||||
if (sf == null) {
|
||||
report(messages.getMessage("err.no.SourceFile.attribute"));
|
||||
return null;
|
||||
}
|
||||
String sourceFile = sf.getSourceFile(cf.constant_pool);
|
||||
String fileBase = sourceFile.endsWith(".java")
|
||||
? sourceFile.substring(0, sourceFile.length() - 5) : sourceFile;
|
||||
int sep = className.lastIndexOf("/");
|
||||
String pkgName = (sep == -1 ? "" : className.substring(0, sep+1));
|
||||
String topClassName = (pkgName + fileBase).replace('/', '.');
|
||||
JavaFileObject fo =
|
||||
fileManager.getJavaFileForInput(location,
|
||||
topClassName,
|
||||
JavaFileObject.Kind.SOURCE);
|
||||
if (fo == null) {
|
||||
report(messages.getMessage("err.source.file.not.found"));
|
||||
return null;
|
||||
}
|
||||
return fo.getCharContent(true).toString();
|
||||
} catch (ConstantPoolException e) {
|
||||
report(e);
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
report(e.getLocalizedMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] splitLines(String text) {
|
||||
if (text == null)
|
||||
return new String[0];
|
||||
|
||||
List<String> lines = new ArrayList<String>();
|
||||
lines.add(""); // dummy line 0
|
||||
try {
|
||||
BufferedReader r = new BufferedReader(new StringReader(text));
|
||||
String line;
|
||||
while ((line = r.readLine()) != null)
|
||||
lines.add(line);
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
return lines.toArray(new String[lines.size()]);
|
||||
}
|
||||
|
||||
private int nextLine(int line) {
|
||||
int i = lineList.indexOf(line);
|
||||
if (i == -1 || i == lineList.size() - 1)
|
||||
return - 1;
|
||||
return lineList.get(i + 1);
|
||||
}
|
||||
|
||||
private JavaFileManager fileManager;
|
||||
private ClassFile classFile;
|
||||
private SortedMap<Integer, SortedSet<Integer>> lineMap;
|
||||
private List<Integer> lineList;
|
||||
private String[] sourceLines;
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import com.sun.tools.classfile.AccessFlags;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.classfile.Attribute;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.ConstantPool;
|
||||
import com.sun.tools.classfile.ConstantPoolException;
|
||||
import com.sun.tools.classfile.Descriptor;
|
||||
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
|
||||
import com.sun.tools.classfile.Instruction;
|
||||
import com.sun.tools.classfile.Method;
|
||||
import com.sun.tools.classfile.StackMapTable_attribute;
|
||||
import com.sun.tools.classfile.StackMapTable_attribute.*;
|
||||
|
||||
import static com.sun.tools.classfile.StackMapTable_attribute.verification_type_info.*;
|
||||
|
||||
/**
|
||||
* Annotate instructions with stack map.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class StackMapWriter extends InstructionDetailWriter {
|
||||
static StackMapWriter instance(Context context) {
|
||||
StackMapWriter instance = context.get(StackMapWriter.class);
|
||||
if (instance == null)
|
||||
instance = new StackMapWriter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected StackMapWriter(Context context) {
|
||||
super(context);
|
||||
context.put(StackMapWriter.class, this);
|
||||
classWriter = ClassWriter.instance(context);
|
||||
}
|
||||
|
||||
public void reset(Code_attribute attr) {
|
||||
setStackMap((StackMapTable_attribute) attr.attributes.get(Attribute.StackMapTable));
|
||||
}
|
||||
|
||||
void setStackMap(StackMapTable_attribute attr) {
|
||||
if (attr == null) {
|
||||
map = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Method m = classWriter.getMethod();
|
||||
Descriptor d = m.descriptor;
|
||||
String[] args;
|
||||
try {
|
||||
ConstantPool cp = classWriter.getClassFile().constant_pool;
|
||||
String argString = d.getParameterTypes(cp);
|
||||
args = argString.substring(1, argString.length() - 1).split("[, ]+");
|
||||
} catch (ConstantPoolException e) {
|
||||
return;
|
||||
} catch (InvalidDescriptor e) {
|
||||
return;
|
||||
}
|
||||
boolean isStatic = m.access_flags.is(AccessFlags.ACC_STATIC);
|
||||
|
||||
verification_type_info[] initialLocals = new verification_type_info[(isStatic ? 0 : 1) + args.length];
|
||||
if (!isStatic)
|
||||
initialLocals[0] = new CustomVerificationTypeInfo("this");
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
initialLocals[(isStatic ? 0 : 1) + i] =
|
||||
new CustomVerificationTypeInfo(args[i].replace(".", "/"));
|
||||
}
|
||||
|
||||
map = new HashMap<Integer, StackMap>();
|
||||
StackMapBuilder builder = new StackMapBuilder();
|
||||
|
||||
// using -1 as the pc for the initial frame effectively compensates for
|
||||
// the difference in behavior for the first stack map frame (where the
|
||||
// pc offset is just offset_delta) compared to subsequent frames (where
|
||||
// the pc offset is always offset_delta+1).
|
||||
int pc = -1;
|
||||
|
||||
map.put(pc, new StackMap(initialLocals, empty));
|
||||
|
||||
for (int i = 0; i < attr.entries.length; i++)
|
||||
pc = attr.entries[i].accept(builder, pc);
|
||||
}
|
||||
|
||||
public void writeInitialDetails() {
|
||||
writeDetails(-1);
|
||||
}
|
||||
|
||||
public void writeDetails(Instruction instr) {
|
||||
writeDetails(instr.getPC());
|
||||
}
|
||||
|
||||
private void writeDetails(int pc) {
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
StackMap m = map.get(pc);
|
||||
if (m != null) {
|
||||
print("StackMap locals: ", m.locals);
|
||||
print("StackMap stack: ", m.stack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void print(String label, verification_type_info[] entries) {
|
||||
print(label);
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
print(" ");
|
||||
print(entries[i]);
|
||||
}
|
||||
println();
|
||||
}
|
||||
|
||||
void print(verification_type_info entry) {
|
||||
if (entry == null) {
|
||||
print("ERROR");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (entry.tag) {
|
||||
case -1:
|
||||
print(((CustomVerificationTypeInfo) entry).text);
|
||||
break;
|
||||
|
||||
case ITEM_Top:
|
||||
print("top");
|
||||
break;
|
||||
|
||||
case ITEM_Integer:
|
||||
print("int");
|
||||
break;
|
||||
|
||||
case ITEM_Float:
|
||||
print("float");
|
||||
break;
|
||||
|
||||
case ITEM_Long:
|
||||
print("long");
|
||||
break;
|
||||
|
||||
case ITEM_Double:
|
||||
print("double");
|
||||
break;
|
||||
|
||||
case ITEM_Null:
|
||||
print("null");
|
||||
break;
|
||||
|
||||
case ITEM_UninitializedThis:
|
||||
print("uninit_this");
|
||||
break;
|
||||
|
||||
case ITEM_Object:
|
||||
try {
|
||||
ConstantPool cp = classWriter.getClassFile().constant_pool;
|
||||
ConstantPool.CONSTANT_Class_info class_info = cp.getClassInfo(((Object_variable_info) entry).cpool_index);
|
||||
print(cp.getUTF8Value(class_info.name_index));
|
||||
} catch (ConstantPoolException e) {
|
||||
print("??");
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_Uninitialized:
|
||||
print(((Uninitialized_variable_info) entry).offset);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Map<Integer, StackMap> map;
|
||||
private ClassWriter classWriter;
|
||||
|
||||
class StackMapBuilder
|
||||
implements StackMapTable_attribute.stack_map_frame.Visitor<Integer, Integer> {
|
||||
|
||||
public Integer visit_same_frame(same_frame frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap m = map.get(pc);
|
||||
assert (m != null);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_same_locals_1_stack_item_frame(same_locals_1_stack_item_frame frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap prev = map.get(pc);
|
||||
assert (prev != null);
|
||||
StackMap m = new StackMap(prev.locals, frame.stack);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_same_locals_1_stack_item_frame_extended(same_locals_1_stack_item_frame_extended frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap prev = map.get(pc);
|
||||
assert (prev != null);
|
||||
StackMap m = new StackMap(prev.locals, frame.stack);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_chop_frame(chop_frame frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap prev = map.get(pc);
|
||||
assert (prev != null);
|
||||
int k = 251 - frame.frame_type;
|
||||
verification_type_info[] new_locals = new verification_type_info[prev.locals.length - k];
|
||||
System.arraycopy(prev.locals, 0, new_locals, 0, new_locals.length);
|
||||
StackMap m = new StackMap(new_locals, empty);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_same_frame_extended(same_frame_extended frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta();
|
||||
StackMap m = map.get(pc);
|
||||
assert (m != null);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_append_frame(append_frame frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap prev = map.get(pc);
|
||||
assert (prev != null);
|
||||
verification_type_info[] new_locals = new verification_type_info[prev.locals.length + frame.locals.length];
|
||||
System.arraycopy(prev.locals, 0, new_locals, 0, prev.locals.length);
|
||||
System.arraycopy(frame.locals, 0, new_locals, prev.locals.length, frame.locals.length);
|
||||
StackMap m = new StackMap(new_locals, empty);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
public Integer visit_full_frame(full_frame frame, Integer pc) {
|
||||
int new_pc = pc + frame.getOffsetDelta() + 1;
|
||||
StackMap m = new StackMap(frame.locals, frame.stack);
|
||||
map.put(new_pc, m);
|
||||
return new_pc;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StackMap {
|
||||
StackMap(verification_type_info[] locals, verification_type_info[] stack) {
|
||||
this.locals = locals;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
private final verification_type_info[] locals;
|
||||
private final verification_type_info[] stack;
|
||||
}
|
||||
|
||||
class CustomVerificationTypeInfo extends verification_type_info {
|
||||
public CustomVerificationTypeInfo(String text) {
|
||||
super(-1);
|
||||
this.text = text;
|
||||
}
|
||||
private String text;
|
||||
}
|
||||
|
||||
private final verification_type_info[] empty = { };
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package com.sun.tools.javap;
|
||||
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.Code_attribute.Exception_data;
|
||||
import com.sun.tools.classfile.Instruction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Annotate instructions with details about try blocks.
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
|
||||
* you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class TryBlockWriter extends InstructionDetailWriter {
|
||||
public enum NoteKind {
|
||||
START("try") {
|
||||
public boolean match(Exception_data entry, int pc) {
|
||||
return (pc == entry.start_pc);
|
||||
}
|
||||
},
|
||||
END("end try") {
|
||||
public boolean match(Exception_data entry, int pc) {
|
||||
return (pc == entry.end_pc);
|
||||
}
|
||||
},
|
||||
HANDLER("catch") {
|
||||
public boolean match(Exception_data entry, int pc) {
|
||||
return (pc == entry.handler_pc);
|
||||
}
|
||||
};
|
||||
NoteKind(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
public abstract boolean match(Exception_data entry, int pc);
|
||||
public final String text;
|
||||
};
|
||||
|
||||
static TryBlockWriter instance(Context context) {
|
||||
TryBlockWriter instance = context.get(TryBlockWriter.class);
|
||||
if (instance == null)
|
||||
instance = new TryBlockWriter(context);
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected TryBlockWriter(Context context) {
|
||||
super(context);
|
||||
context.put(TryBlockWriter.class, this);
|
||||
constantWriter = ConstantWriter.instance(context);
|
||||
}
|
||||
|
||||
public void reset(Code_attribute attr) {
|
||||
indexMap = new HashMap<Exception_data, Integer>();
|
||||
pcMap = new HashMap<Integer, List<Exception_data>>();
|
||||
for (int i = 0; i < attr.exception_table.length; i++) {
|
||||
Exception_data entry = attr.exception_table[i];
|
||||
indexMap.put(entry, i);
|
||||
put(entry.start_pc, entry);
|
||||
put(entry.end_pc, entry);
|
||||
put(entry.handler_pc, entry);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDetails(Instruction instr) {
|
||||
writeTrys(instr, NoteKind.END);
|
||||
writeTrys(instr, NoteKind.START);
|
||||
writeTrys(instr, NoteKind.HANDLER);
|
||||
}
|
||||
|
||||
public void writeTrys(Instruction instr, NoteKind kind) {
|
||||
String indent = space(2); // get from Options?
|
||||
int pc = instr.getPC();
|
||||
List<Exception_data> entries = pcMap.get(pc);
|
||||
if (entries != null) {
|
||||
for (ListIterator<Exception_data> iter =
|
||||
entries.listIterator(kind == NoteKind.END ? entries.size() : 0);
|
||||
kind == NoteKind.END ? iter.hasPrevious() : iter.hasNext() ; ) {
|
||||
Exception_data entry =
|
||||
kind == NoteKind.END ? iter.previous() : iter.next();
|
||||
if (kind.match(entry, pc)) {
|
||||
print(indent);
|
||||
print(kind.text);
|
||||
print("[");
|
||||
print(indexMap.get(entry));
|
||||
print("] ");
|
||||
if (entry.catch_type == 0)
|
||||
print("finally");
|
||||
else {
|
||||
print("#" + entry.catch_type);
|
||||
print(" // ");
|
||||
constantWriter.write(entry.catch_type);
|
||||
}
|
||||
println();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void put(int pc, Exception_data entry) {
|
||||
List<Exception_data> list = pcMap.get(pc);
|
||||
if (list == null) {
|
||||
list = new ArrayList<Exception_data>();
|
||||
pcMap.put(pc, list);
|
||||
}
|
||||
if (!list.contains(entry))
|
||||
list.add(entry);
|
||||
}
|
||||
|
||||
private Map<Integer, List<Exception_data>> pcMap;
|
||||
private Map<Exception_data, Integer> indexMap;
|
||||
private ConstantWriter constantWriter;
|
||||
}
|
@ -9,6 +9,7 @@ err.file.not.found=file not found: {0}
|
||||
err.h.not.supported=-h is no longer available - use the 'javah' program
|
||||
err.incompatible.options=bad combination of options: {0}
|
||||
err.internal.error=internal error: {0} {1} {2}
|
||||
err.invalid.arg.for.option=invalid argument for option: {0}
|
||||
err.ioerror=IO error reading {0}: {1}
|
||||
err.missing.arg=no value given for {0}
|
||||
err.no.classes.specified=no classes specified
|
||||
@ -16,6 +17,8 @@ err.not.standard.file.manager=can only specify class files when using a standard
|
||||
err.unknown.option=unknown option: {0}
|
||||
err.verify.not.supported=-verify not supported
|
||||
err.Xold.not.supported.here=-Xold must be given as the first option
|
||||
err.no.SourceFile.attribute=no SourceFile attribute
|
||||
err.source.file.not.found=source file not found
|
||||
|
||||
main.usage.summary=\
|
||||
Usage: {0} <options> <classes>\n\
|
||||
|
116
langtools/test/tools/javap/T6824493.java
Normal file
116
langtools/test/tools/javap/T6824493.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6824493
|
||||
* @summary experimental support for additional info for instructions
|
||||
* @compile -g T6824493.java
|
||||
* @run main T6824493
|
||||
*/
|
||||
public class T6824493 {
|
||||
public static void main(String... args) {
|
||||
new T6824493().run();
|
||||
}
|
||||
|
||||
void run() {
|
||||
// for each of the options, we run javap and check for some
|
||||
// marker strings in the output that generally indicate the
|
||||
// presence of the expected output, without being as specific
|
||||
// as a full golden file test.
|
||||
test("-XDdetails:source",
|
||||
"for (int i = 0; i < 10; i++) {",
|
||||
"System.out.println(s + i);");
|
||||
|
||||
test("-XDdetails:tryBlocks",
|
||||
"try[0]",
|
||||
"end try[0]",
|
||||
"catch[0]");
|
||||
|
||||
test("-XDdetails:stackMaps",
|
||||
"StackMap locals: this java/lang/String int",
|
||||
"StackMap stack: java/lang/Throwable");
|
||||
|
||||
test("-XDdetails:localVariables",
|
||||
"start local 3 // java.util.List list",
|
||||
"end local 3 // java.util.List list");
|
||||
|
||||
test("-XDdetails:localVariableTypes",
|
||||
"start generic local 3 // java.util.List<java.lang.String> list",
|
||||
"end generic local 3 // java.util.List<java.lang.String> list");
|
||||
|
||||
if (errors > 0)
|
||||
throw new Error(errors + " errors found");
|
||||
}
|
||||
|
||||
void test(String option, String... expect) {
|
||||
String[] args = {
|
||||
"-c",
|
||||
"-classpath",
|
||||
testSrc + File.pathSeparator + testClasses,
|
||||
option,
|
||||
"Test"
|
||||
};
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
int rc = com.sun.tools.javap.Main.run(args, pw);
|
||||
if (rc != 0) {
|
||||
error("unexpected return code from javap: " + rc);
|
||||
return;
|
||||
}
|
||||
|
||||
String out = sw.toString();
|
||||
System.out.println(out);
|
||||
for (String e: expect) {
|
||||
if (!out.contains(e))
|
||||
error("Not found: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
System.err.println("Error: " + msg);
|
||||
errors++;
|
||||
}
|
||||
|
||||
private int errors;
|
||||
private String testSrc = System.getProperty("test.src", ".");
|
||||
private String testClasses = System.getProperty("test.classes", ".");
|
||||
}
|
||||
|
||||
class Test {
|
||||
void m(String s) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
List<String> list = null;
|
||||
System.out.println(s + i);
|
||||
} catch (NullPointerException e) {
|
||||
System.out.println("catch NPE");
|
||||
} finally {
|
||||
System.out.println("finally");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user