2011-08-19 6 views
11

これは学問的な演習です(免責事項)。Javaリフレクション実行時のパフォーマンス

他の人と競合する可能性があるため、私はとなるべく早くという利益を得るアプリケーションを構築しています。

私は、リフレクションを使ってクラスを宣言することは、標準的な宣言ではなく、大きなペナルティを被ることを知っています。私は標準的な方法でそれを使用する場合

Class mDefinition = Class.forName("MySpecialClassString"); 
Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class}); 
myClass = (MySpecialClass) mConstructor.newInstance(this); 

はしかし、myClassを宣言した後myClass.myMethod()は、私はまた、パフォーマンスの豚苦しむだろうか、私は標準的な方法でクラスを宣言していたかのようにそれは同じでしょうか?

答えて

14

最初にオブジェクトをインスタンス化すると、パフォーマンスが低下します。クラスがロードされると、クラスが正常にインスタンス化された場合と同じになり、それ以上のパフォーマンス上のペナルティは発生しません。

さらに、リフレクションを使用してメソッドを呼び出すと、約15回のパフォーマンス低下(Javaではデフォルト)が発生します。その後、反映された呼び出しはJVMによって静的にコンパイルされた呼び出しとまったく同じになりますコール。したがって、JVMによってバイトコードが再コンパイルされると、繰り返し反映されたメソッド呼び出しでもパフォーマンスが低下することはありません。

ことの詳細については、これら2つのリンクを参照してください:

+0

です。これらの最後のカップルで本当に役に立つと証明されました。 – Frankie

7

クラスがロードされたら、あなたはうまくいくはずです。オーバーヘッドは、クラスを表すランタイム構造体などを検査することに関連しています。標準的な方法でメソッドを呼び出す必要がありますが、名前やシグネチャでメソッドを検索すると、オーバーヘッドが発生します。

+1

1は、合意された - ワンショット動的な検索のための多大な費用があってはなりません。 –

+0

@Chris私はいくつかのテストを行ってきました。あなたはあなたの前提に忠実です。事前にこれをクリアしていただきありがとうございます。 – Frankie

2

クリス・トンプソンの答えはマークです。しかし、私はあなたのコード例に混乱しています。

これは、動的にクラスをロードします:

Class mDefinition = Class.forName("MySpecialClassString"); 

これは、引数としてその同じクラスのインスタンスを受け取り、あなたのクラスのためのContructorを取得します。また、あなたがMySpecialClass.classとコンパイル時にクラスにアクセスしていることに注意してください:これはコンストラクタにthisを渡すことによってMySpecialClassをインスタンス化され

Constructor mConstructor = mDefinition.getConstructor(new Class[]{MySpecialClass.class}); 

:コンストラクタの引数に基づいて

myClass = (MySpecialClass) mConstructor.newInstance(this); 

、その平均値を行います私たちはMySpecialClassのインスタンスメソッドにありますか?非常に混乱。

EDIT:これは私が見に期待したものに近いです:MySpecialInterfaceあなた動的にロードされたクラスとやり取りするためのインタフェースである

Class<?> mDefinition = Class.forName("MySpecialClassString"); 

//constructor apparently takes this as argument 
Class<?> constructorArgType = this.getClass(); //could be ThisClassName.class 

Constructor<?> mConstructor = mDefinition.getConstructor(constructorArgType); 

MySpecialInterface mySpecialInstance = (MySpecialInterface)mConstructor.newInstance(this); 

:とにかく

interface MySpecialInterface { 
    //methods used to interface with dynamically loaded classes 
} 

をしてください私が誤解しているか、ここでベースを外しているかどうか、私に知らせてください。

+0

私はちょうど今反射を使用し始めているので、おそらく正しいでしょう。システムがどのように動作するかについて、非常に速く簡単に説明しましょう。 ClassA_interaction、ClassB_object、ClassC_logicの3つのクラスがあります。ClassA_interactionはいくつかのClassB_objectを起動し、それらに位置を与えます。すべてのClassB_objectはリフレクションを使用してClassC_logicを起動します。 ClassC_logicは、ClassB_object上に存在する関数を呼び出さなければならないので、 'this'(ClassB_object)でフィードされます。 これは面倒かもしれませんが、動作します。別のアプローチをとることをお勧めしますか?私のコードを見る時間を取ってくれたことに感謝します。 – Frankie

+0

私は個人的に動的なクラスローディングで作業していないと言わざるを得ません。なぜなら、私は誰かからの確認を望んでいたからです。しかし、私の理解では、コード内のクラスを直接参照したり、コンパイル時にそのクラスにアクセスすることさえできれば、それを動的にロードする必要はありません。しかし、静的にロードされた 'Foo'が抽象クラスまたはインタフェースであり、動的にロードされるクラスが' Foo'を拡張/実装すると意味があります。こうすることで、クラスを動的にロードしてインスタンス化した後、それを 'Foo'にキャストして、それ以上のリフレクションなしに対話できます。 –

+0

もちろん、 'Foo'は、これらの動的にロードされたクラスを抽象的な/インターフェースメソッド宣言の形でやりたいと思っていることをすべて知っている必要があります。 –

関連する問題