java - 如何在方法中检索任何内容
java - How to retrieve anything inside method
据我所知,java 无法检索方法内部的任何内容。所以我在 javac.
中使用选项 -g 或 -g:vars
例如:
class Test {
int a=0;
void method(boolean boo){
String b;
try
{
new Thread().sleep(1000);
}
catch(InterruptedException e){}
JOptionPane.showMessageDialog(null,"test");
BufferedImage image=ImageIO.read(new File("C:\file.png"));
}
}
所以,我使用 BCEL 来检索局部变量。
import org.apache.bcel.classfile.*;
import org.apache.bcel.Repository;
class javap
{
public static void main(String[]args)
{
try
{
JavaClass jc = Repository.lookupClass("test");
ConstantPool constantPool = jc.getConstantPool();
Method [] method=jc.getMethods();
for (Method m : method)
{
LocalVariableTable lvt=m.getLocalVariableTable();
LocalVariable[] lv=lvt.getLocalVariableTable();
for(LocalVariable l : lv)
{
System.out.println(l.getName()+" : "+l.getSignature());
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
但是如果变量没有像String b
那样被初始化,它就不起作用了。此外,我想跟踪构造函数调用,如 new Thread()
或 new File()
以及静态方法的调用和 JFileChooser
内部的初始化,如 new File
和 JOptionPane
。所以我想在输出中看到 Thread
、String b
、JOptionPane
、ImageIO
和 File
.
我应该怎么做才能让它们打印在我的程序中?
您根本无法获得 b
变量,因为 java 编译器(至少 javac 和 ecj)不会将其放入生成的 class 文件中all:如果未分配变量,则不分配变量槽且不存储在 LocalVariableTable 中。您可以创建名称较长的未使用变量,例如 String blahblah;
,编译 class,在文本编辑器中打开编译后的 .class 文件并搜索 blahblah
字符串。你不会找到它。所以BCEL不能帮你找到不存在的变量。
如果你想跟踪新对象的创建和静态方法的调用,你可以扫描方法字节码。使用 BCEL 执行此操作的最简单方法是使用 MethodGen
(即使您不想生成新方法)。这是完整的代码:
import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.NEW;
class javap
{
public static void main(String[]args)
{
try
{
JavaClass jc = Repository.lookupClass("Test");
ConstantPool constantPool = jc.getConstantPool();
Method [] method=jc.getMethods();
for (Method m : method)
{
LocalVariableTable lvt=m.getLocalVariableTable();
LocalVariable[] lv=lvt.getLocalVariableTable();
for(LocalVariable l : lv)
{
System.out.println(l.getName()+" : "+l.getSignature());
}
}
ConstantPoolGen cpg = new ConstantPoolGen(constantPool);
for(Method m : method)
{
MethodGen mg = new MethodGen(m, m.getName(), cpg);
for(InstructionHandle ih = mg.getInstructionList().getStart();
ih != null; ih = ih.getNext())
{
if(ih.getInstruction() instanceof NEW)
{
NEW newInst = ((NEW)ih.getInstruction());
String className = constantPool.getConstantString(
newInst.getIndex(), Constants.CONSTANT_Class);
System.out.println("Class instantiation: "+className);
}
if(ih.getInstruction() instanceof INVOKESTATIC)
{
INVOKESTATIC newInst = ((INVOKESTATIC)ih.getInstruction());
String className = constantPool.getConstantString(
((ConstantMethodref) constantPool
.getConstant(newInst.getIndex()))
.getClassIndex(),
Constants.CONSTANT_Class);
System.out.println("Static call: "+className);
}
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
输出如下:
this : LTest;
this : LTest;
boo : Z
Class instantiation: java/lang/Thread
Static call: java/lang/Thread
Static call: javax/swing/JOptionPane
Class instantiation: java/io/File
Static call: javax/imageio/ImageIO
请注意,您有两次 java/lang/Thread
,因为 new Thread()
被捕捉为对象创建而 Thread.sleep()
被捕捉为静态方法调用。
据我所知,java 无法检索方法内部的任何内容。所以我在 javac.
中使用选项 -g 或 -g:vars例如:
class Test {
int a=0;
void method(boolean boo){
String b;
try
{
new Thread().sleep(1000);
}
catch(InterruptedException e){}
JOptionPane.showMessageDialog(null,"test");
BufferedImage image=ImageIO.read(new File("C:\file.png"));
}
}
所以,我使用 BCEL 来检索局部变量。
import org.apache.bcel.classfile.*;
import org.apache.bcel.Repository;
class javap
{
public static void main(String[]args)
{
try
{
JavaClass jc = Repository.lookupClass("test");
ConstantPool constantPool = jc.getConstantPool();
Method [] method=jc.getMethods();
for (Method m : method)
{
LocalVariableTable lvt=m.getLocalVariableTable();
LocalVariable[] lv=lvt.getLocalVariableTable();
for(LocalVariable l : lv)
{
System.out.println(l.getName()+" : "+l.getSignature());
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
但是如果变量没有像String b
那样被初始化,它就不起作用了。此外,我想跟踪构造函数调用,如 new Thread()
或 new File()
以及静态方法的调用和 JFileChooser
内部的初始化,如 new File
和 JOptionPane
。所以我想在输出中看到 Thread
、String b
、JOptionPane
、ImageIO
和 File
.
我应该怎么做才能让它们打印在我的程序中?
您根本无法获得 b
变量,因为 java 编译器(至少 javac 和 ecj)不会将其放入生成的 class 文件中all:如果未分配变量,则不分配变量槽且不存储在 LocalVariableTable 中。您可以创建名称较长的未使用变量,例如 String blahblah;
,编译 class,在文本编辑器中打开编译后的 .class 文件并搜索 blahblah
字符串。你不会找到它。所以BCEL不能帮你找到不存在的变量。
如果你想跟踪新对象的创建和静态方法的调用,你可以扫描方法字节码。使用 BCEL 执行此操作的最简单方法是使用 MethodGen
(即使您不想生成新方法)。这是完整的代码:
import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ConstantMethodref;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.LocalVariableTable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.INVOKESTATIC;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.NEW;
class javap
{
public static void main(String[]args)
{
try
{
JavaClass jc = Repository.lookupClass("Test");
ConstantPool constantPool = jc.getConstantPool();
Method [] method=jc.getMethods();
for (Method m : method)
{
LocalVariableTable lvt=m.getLocalVariableTable();
LocalVariable[] lv=lvt.getLocalVariableTable();
for(LocalVariable l : lv)
{
System.out.println(l.getName()+" : "+l.getSignature());
}
}
ConstantPoolGen cpg = new ConstantPoolGen(constantPool);
for(Method m : method)
{
MethodGen mg = new MethodGen(m, m.getName(), cpg);
for(InstructionHandle ih = mg.getInstructionList().getStart();
ih != null; ih = ih.getNext())
{
if(ih.getInstruction() instanceof NEW)
{
NEW newInst = ((NEW)ih.getInstruction());
String className = constantPool.getConstantString(
newInst.getIndex(), Constants.CONSTANT_Class);
System.out.println("Class instantiation: "+className);
}
if(ih.getInstruction() instanceof INVOKESTATIC)
{
INVOKESTATIC newInst = ((INVOKESTATIC)ih.getInstruction());
String className = constantPool.getConstantString(
((ConstantMethodref) constantPool
.getConstant(newInst.getIndex()))
.getClassIndex(),
Constants.CONSTANT_Class);
System.out.println("Static call: "+className);
}
}
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
输出如下:
this : LTest;
this : LTest;
boo : Z
Class instantiation: java/lang/Thread
Static call: java/lang/Thread
Static call: javax/swing/JOptionPane
Class instantiation: java/io/File
Static call: javax/imageio/ImageIO
请注意,您有两次 java/lang/Thread
,因为 new Thread()
被捕捉为对象创建而 Thread.sleep()
被捕捉为静态方法调用。