2015-12-03 4 views
17

は、私が見つかりました:最初にクラスロード処理中にClass <?>オブジェクトを作成するのは誰ですか? <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html" rel="nofollow noreferrer">documentation</a>で

Classオブジェクトは、クラスがロードされる際にJava仮想マシン によって自動的に構成され、クラスローダでdefineClassメソッド への呼び出しでされています。

the source codeを確認しましたが、場所が見つかりませんでしたdefineClassと呼びます。 loadClassメソッドから取得します。

scheme

ピクチャーsource

+1

JVMの内部(マジック!)を扱うとき、ネイティブコード(C/C++/asm)で状況が起こっている可能性があるというのは良い疑いがあります。 – Nayuki

+0

確かにそれは可能かもしれませんが、質問は次のとおりです:それはいつ(クラスオブジェクトが現れる)ですか?実装言語は関係ありません –

答えて

10

defineClass()方法はClassLoader#loadClass()の呼び出し中に呼び出されます。 あなたは私、してください、誰と通話defineClass方法このスキームに従って示すことができました。しかしながら、これはjava.lang.ClassLoaderクラス内ではなく、そのサブクラスの1つ、例えば、 URLClassLoader#findClass()

ClassLoader#defineClass()への呼び出しがネイティブ方法defineClass1()またはdefineClass2()の1への呼び出しで終わります。これらのメソッドのC実装はOpenJDKのsrc/share/native/java/lang/ClassLoader.cにあります。

5

java.lang.ClassLoaderは、このような大きなクラスです。 GrepCodeリンク(はjava 6-b14バージョン)を使用すると、267行目にpublic loadClassメソッドがあります。

この方法では、ライン308で保護loadClassメソッドを呼び出し、このメソッドは使用してprevioslyロードされたクラスをロードしよう:、両端にネイティブメソッドを呼び出します

  • findLoadedClass

  • parent.loadClassを呼び出す
  • findBootstrapClass0ネイティブメソッドparent,
  • 最後にクラスが見つからない場合は10。

ClassLoaderは既にロードされているクローズを再利用しようとしているので、これは重要なことです。

ただし、defineClassはどこに呼び出されますか?この抽象クラスからの場所はありませんが、GrepCodeの参照ツールを使用して、どこで使用されているのかを調べる場合はdefineClasssee here results)、多くの具体的なクラスがあります。具体的なクラスは末尾にdefinClassとなります。

それは他の人がそのように上の呼び出し、...と、独自のloadClassを呼び出しながら、これらのクラスのいくつかは、defineClassをオーバーライドし、簡単ではないですが、最終的にはdefineClassを呼び出します。

ClassLoaderdefineClassはJVM の責任である3つのネイティブメソッド魔法の一つで終わることを忘れないでください:defineClass0defineClass1および/またはdefineClass2

編集

からJava_java_lang_ClassLoader_defineClass0を呼び出すdefineClass0ネイティブ機能ClassLoader.cと1と2の関数で同じです。

この関数は、jvm.hで定義され、openjdk\hotspot\src\share\vm\prims\jvm.cppに実装されたJVM_DefineClassWithSourceを使用して、必要なクラスを作成します。

この最後のファイルは、最終的に必要なクラスを作成する関数jvm_define_class_commonを定義しています。最後に、この関数はJNIHandles::make_localを呼び出してクラスを割り当てます。この最後の機能のコードはopenjdk\hotspot\src\share\vm\runtime\jniHandles.cpp

でご覧になれます。

1
class NetworkClassLoader extends ClassLoader { 
     String host; 
     int port; 

     public Class findClass(String name) { 
      byte[] b = loadClassData(name); 
      return defineClass(name, b, 0, b.length); 
     } 

     private byte[] loadClassData(String name) { 
      // load the class data from the connection 
       . . . 
     } 
    } 
+0

これはOracle dosumentation.defineClassの抽出ファイルです。ClassLoaderのメソッドで、バイト配列をClassクラスのインスタンスに変換します。 私はそれが役に立ちそうです – Hiren