0

私が知っていることから、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.

プログラムでそれらを印刷するにはどうすればよいですか?

4

1 に答える 1

3

bJavaコンパイラ(少なくともjavacとecj)は生成されたクラスファイルに変数をまったく入れないため、変数を取得することはできません.変数が割り当てられていない場合、変数スロットは割り当てられず、LocalVariableTableに格納されません. のような長い名前の未使用の変数を作成しString blahblah;、クラスをコンパイルし、コンパイルされた .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ため、2 回あることに注意してください。new Thread()Thread.sleep()

于 2015-06-23T05:36:33.043 に答える