2017-01-04 4 views
1

クラスに追加した整数配列フィールドにアクセスするためにバイトコード計測を使用したいと思います。これを行うには、クラスファイルのフィールドのインデックスが必要ですが、私はそれを見つけることができません。代わりに、より詳細に説明するのバイトコードでの使用のためにJavassistを使用してクラスの宣言フィールドのインデックスを取得

(希望は、そのインデックスIは、ローカル変数テーブルから取得しまし宣言されたローカルの整数、である):

desired = Server.rand.nextInt(4); 

私がやりたい:

desired = _MyField[Server.rand.nextInt(_MyField.length)]; 
あろうJASMで

:フィールドはJavassistのを使用して追加され

// field reference to later access an index in the array 
aload <local variable index of "this"> (push reference of class) 
getfield <fieldindex> (pop reference, push field reference to stack) 

// rand is a public static field in class Server 
getstatic java.util.Random com.wurmonline.server.Server.rand 

// field reference to pass to arraylength and the Random.nextInt(int) call 
aload <local variable index of "this"> 
getfield <fieldindex> (push reference of array) 

arraylength (pop reference, push array.length value) 
invokevirtual int java.util.Random.nextInt(int) (pop length for rng, push index) 
iaload (pop index, push integer value from array index) 
istore <index of local variable "desired"> (pop value, store in variable) 

は、SBがStringBuilあるましたフィールド初期化子(例えば、 "新しいINT [] {N、N、N、N、N};"):

ctClass.addField(
    new CtField(
      HookManager.getInstance().getClassPool().get("[I"), 
      "_OtherServerMissions", 
      ctClass), 
    sb.toString()); 

DirtyJOE、Java8 /メジャークラスファイルのバージョン52で動作するバイトコード・エディタを使用してクラスファイルを見ると、フィールドのインデックス値が見つかりません。また、CtField、または該当するAttributeInfoを使用して検索することもできません。

for (CtField ctField : ctClass.getDeclaredFields()) 

ここで、フィールドインデックスを取得する場所が不思議に思えます。

私の説明がこの問題に精通している貧しい人々のために十分に明確であることを望みます。

答えて

0

時々、問題を他の人に説明する方法で問題を書くのに役立ちます。

GETFIELDオペコードに渡されるFIELDINDEXは、クラスの定数プールへの参照です。クラスの定数プールにFieldrefInfoを追加する必要があります。 addFieldrefInfo()の戻り値は定数プール内のインデックスです。

ConstPool constPool = ctClass.getClassFile().getConstPool(); 

[...] 

sb = new StringBuilder(); 
sb.append("new int[] { "); 
for (int i : _OtherServerMissions) 
    sb.append(String.format("%d,", i)); 
sb.deleteCharAt(sb.lastIndexOf(",")); 
sb.append(" };"); 

ctClass.addField(
     new CtField(
       HookManager.getInstance().getClassPool().get("[I"), 
       "_OtherServerMissions", 
       ctClass), 
     sb.toString()); 

int otherFieldIndex = constPool.addFieldrefInfo(constPool.getThisClassInfo(), "_OtherServerMissions", "[I"); 
logger.log(Level.INFO, "Added OtherFieldIndex as " + otherFieldIndex); 

また、(該当する場合)GETFIELDを使用する前に、スタック上のクラスのインスタンスの参照をプッシュし、「この」の指標を決定する必要があります。

int thisIndex = -1; 
LocalVariableAttribute lva = (LocalVariableAttribute)generateMission 
    .getMethodInfo() 
    .getCodeAttribute() 
    .getAttribute(LocalVariableAttribute.tag); 

for (int i = 0; thisIndex < 0 && i < lva.tableLength(); i++) { 
    if (lva.variableName(i).equals("this")) 
     thisIndex = lva.index(i); 
} 

すでにローカル変数テーブルにない場合は、この時点で追加する方法がわかりません。または、どのようにしてローカル変数テーブルに一般的に追加するか。あなたが知っていれば、コメントを残しておきましょう。

固定質問に、ここで概説した値で使用される正しいJavaアセンブリコードが含まれるようになりました。

関連する問題