クラスロードについてもう少し調べてみた
前回の記事と同様に、クラスロードに関してはVM次第な部分があるので、参考程度でお願いします。
前回からさらに
init/createdのログをみてもらうとわかるのだけれど、この時点でClassLoaderSampleがすでにクラスロードされている。
ClassLoaderSampleには、Buzz4を返すメソッドがあるにもかかわらず、Buzz4はロードされておらず、クラスロードされるのは、実際にBuzz4をnewしたときとなっている。
逆にBuzz/Buzz3はClassLoaderSampleがロードされた段階で、ClassLoaderに登録されてしまっている
ようするに
クラスがロードされるときは、自クラスを構成するクラスを全部読み込んでるわけではなく、キャストの必要なものだけがロードされているようだ。
返り値の型とreturn時の型が同じであれば、呼ぶまでは何もロードしていない。
ちなみに
フィールドでも同じ現象が起きるみたい。
また別の機会にでも検証してみようかな
環境
JDK1.6
出力結果
### init #### class limelabo.ClassLoaderSample class limelabo.ClassLoaderSample$Buzz class limelabo.ClassLoaderSample$Buzz3 #### created #### class limelabo.ClassLoaderSample class limelabo.ClassLoaderSample$Buzz class limelabo.ClassLoaderSample$Buzz3 #### Buzz3 #### class limelabo.ClassLoaderSample class limelabo.ClassLoaderSample$Buzz class limelabo.ClassLoaderSample$Buzz3 #### Buzz4 #### class limelabo.ClassLoaderSample class limelabo.ClassLoaderSample$Buzz class limelabo.ClassLoaderSample$Buzz3 class limelabo.ClassLoaderSample$Buzz4
ソースコード
package limelabo; import java.lang.reflect.Field; import java.util.Vector; public class ClassLoaderSample { public static void main(String[] args) { ClassLoader cl = ClassLoader.getSystemClassLoader(); printClassLoader("### init ####", cl); ClassLoaderSample hoge = new ClassLoaderSample(); printClassLoader("#### created ####", cl); hoge.createBuzz3(); printClassLoader("#### Buzz3 ####", cl); hoge.createBuzz4(); printClassLoader("#### Buzz4 ####", cl); } private Buzz createBuzz3() { return new Buzz3(); } private Buzz4 createBuzz4() { return new Buzz4(); } static class Buzz { } static class Buzz3 extends Buzz { } static class Buzz4 extends Buzz { } /** * @param message * @param cl */ private static void printClassLoader(String message, ClassLoader cl) { System.out.println(message); Class<?> c = cl.getClass(); // ClassLoaderまでさかのぼる for (; !ClassLoader.class.getName().equals(c.getName()); c = c.getSuperclass()) { } try { Field classesField = c.getDeclaredField("classes"); classesField.setAccessible(true); Vector<Class> classes = (Vector<Class>) classesField.get(cl); for (Class loadedClass : classes) { System.out.println(loadedClass); } } catch (Exception e) { // とりあえず無視 e.printStackTrace(); } } }