2011-12-06 8 views
3

私は、実行時オブジェクトが参照しているオブジェクトをリストする方法を見つけることを試みています。私はovを使ってjvmに問い合わせる方法があることを知っていますが、私がやりたいことはプログラムの中からそれを照会することです。使用できるAPIはありますか?オブジェクトの意味を知るにはどうしたらいいですか?

+0

機能要件でない場合は、プロファイラまたはデバッガを使用できます。私はjhat/jstatがスナップショットをダンプするのに役立つと思うので、あなたがオフラインのイントロスペクションをしたいのであれば、それは簡単でしょう。それが機能的要件であれば、それは興味深いものです! – questzen

答えて

3

Reflection(java.lang.reflect)で行うことができます。

説明はin this articleです。リフレクションで

public class Secret { 

    private String secretCode = "It's a secret"; 

    private String getSecretCode(){ 
     return secretCode;  
    } 
} 

は、あなたが(私立含む)、そのメンバーのすべてにアクセスすることができ、それらの値を含む:基本的には、民間のメンバーを持っているこのクラスを与えられました。そして、あなたが参照しているものを見るために、そのデータメンバー全員を見ています(もちろん、他のオブジェクトも参照している場合は、プロセスを繰り返すことができます)。メンバーにアクセスする方法は次のとおりです(このコードにはメソッドも表示されていますが、データに興味があるだけの場合は必要ありませんが、その部分を引き出す正当な理由は見当たりませんでした)。

import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
import java.lang.reflect.InvocationTargetException; 

public class Hacker { 

    private static final Object[] EMPTY = {}; 

    public void reflect(Object instance) 
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
     Class secretClass = instance.getClass(); 

     // Print all the method names & execution result 
     Method methods[] = secretClass.getDeclaredMethods(); 
     System.out.println("Access all the methods"); 
     for (int i = 0; i < methods.length; i++) { 
      System.out.println("Method Name: " + methods[i].getName()); 
      System.out.println("Return type: " + methods[i].getReturnType()); 
      methods[i].setAccessible(true); 
      System.out.println(methods[i].invoke(instance, EMPTY) + "\n"); 
     } 

     // Print all the field names & values 
     Field fields[] = secretClass.getDeclaredFields(); 
     System.out.println("Access all the fields"); 
     for (int i = 0; i < fields.length; i++){ 
      System.out.println("Field Name: " + fields[i].getName()); 
      fields[i].setAccessible(true); 
      System.out.println(fields[i].get(instance) + "\n"); 
     } 
    } 

    public static void main(String[] args){ 

     Hacker newHacker = new Hacker(); 

     try { 
      newHacker.reflect(new Secret()); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

HackerSecretmain以外)に結び付けられていないことをより明確にするために、元のコードにバグを修正して少し変更しました。

更新:基底クラスからフィールドについて以下のご質問は、ここに(私はあなたがObjectのフィールドを列挙しようとしたくないと仮定したことありません更新Hackerですので、私は停止しました再そこ):

import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
import java.lang.reflect.InvocationTargetException; 

public class Hacker { 

    private static final Object[] EMPTY = {}; 

    public void reflect(Object instance) 
    throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
     Class cls = instance.getClass(); 

     while (cls != null && cls != Object.class) { 
      System.out.println("From class: " + cls.getName()); 

      // Print all the method names & execution result 
      Method methods[] = cls.getDeclaredMethods(); 
      System.out.println("Access all the methods"); 
      for (int i = 0; i < methods.length; i++) { 
       System.out.println("Method Name: " + methods[i].getName()); 
       System.out.println("Return type: " + methods[i].getReturnType()); 
       methods[i].setAccessible(true); 
       System.out.println(methods[i].invoke(instance, EMPTY) + "\n"); 
      } 

      // Print all the field names & values 
      Field fields[] = cls.getDeclaredFields(); 
      System.out.println("Access all the fields"); 
      for (int i = 0; i < fields.length; i++){ 
       System.out.println("Field Name: " + fields[i].getName()); 
       fields[i].setAccessible(true); 
       System.out.println(fields[i].get(instance) + "\n"); 
      } 

      // Go to the base class 
      cls = cls.getSuperclass(); 
     } 
    } 

    public static void main(String[] args){ 

     Hacker newHacker = new Hacker(); 

     try { 
      newHacker.reflect(new Secret()); 
     } 
     catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

public class BaseSecret { 

    private String baseSecretCode = "It's a base secret"; 

} 

と組み合わせます

あなたが得る:

$ java Hacker 
From class: Secret 
Access all the methods 
Method Name: getSecretCode 
Return type: class java.lang.String 
It's a secret 

Access all the fields 
Field Name: secretCode 
It's a secret 

From class: BaseSecret 
Access all the methods 
Access all the fields 
Field Name: baseSecretCode 
It's a base secret
+0

ありがとう。 APIは、getDeclaredFields()は継承されたメソッドを除外していると言います。これらを見つける方法も知っていますか? – uzilan

+0

@uzilan:['getSuperclass'](http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getSuperclass())を使用してリンス/リピートします。私は例を追加しました。 –

+0

もう一度ありがとうございます。明らかに、私はAPIの読解スキルを実践しなければなりません:) – uzilan

-1

あなたがオブジェクトの実行時のクラスを取得するためにObjectクラスのはgetClass()メソッドを使用することができます。

関連する問題