2015-07-15 11 views
5

Jestem trochę zmieszany, gdy klasa faktycznie jest ładowana przez maszynę JVM. Zauważyłem, że program ładujący klasy załaduje klasę, gdy odwołanie się do klasy.Nieporozumienia związane z ładowaniem klasy

Używam środowiska java6 i uruchamiam z opcją -verbose: class, aby śledzić ładowanie klasy. Na przykład:

MyObject obj = new MyObject(); //MyObject.class will be loaded 

Jednak w tym przypadku

// ClassC.java 
package com.gogog22510.test; 
public class ClassC {} 

// ClassB.java 
package com.gogog22510.test; 
public class ClassB extends ClassC {} 

// ClassA.java 
package com.gogog22510.test; 
public class ClassA { 
    public ClassC test() { 
     return new ClassB(); 
    } 
} 

kiedy mój program testowy zainicjować ClassA, to załadowanie wszystkich ClassA, ClassB i ClassC choć nie powoływać test()

// TestClassLoad.java 
package com.gogog22510.test; 
public class TestClassLoad { 
    public static void main(String[] args) { 
     // initialize ClassA 
     System.out.println("start load ClassA"); 
     new ClassA(); 
    } 
} 

konsola:

[załadowany TestClassLoad z pliku: /.../ bin /]
obciążenia początek ClassA
[załadowany Classa z pliku:/C: /.../ bin /]
[załadowany ClassC z pliku:/C: /.../ bin /]
[Loaded ClassB z pliku:/C: /.../ bin /]

Ale jeśli zmienię test() metoda jest zwracany typ tak :

// ClassA.java 
package com.gogog22510.test; 
public class ClassA { 
    public ClassB test() { 
     return new ClassB(); 
    } 
} 

ClassLoader załaduje ClassA tylko do przestrzeni perm, chyba że wywołam metodę test().

konsoli:

[załadowany TestClassLoad z pliku: /.../ bin /]
obciążenia początek ClassA
[załadowany Classa z pliku:/C: /.../ Pojemnik /]

Dlaczego obciążenie ClassLoader wszystkie trzy klasy przed jawnie wywołać metodę?

+2

_it załaduje wszystkie klasy A, ClassB i ClassC_ Jak możesz powiedzieć? –

+3

Nie mogę odtworzyć tego zachowania, tylko ładowana jest klasa Class http://ideone.com/Gw9QDU – Pshemo

+0

Ten kod źródłowy nie jest wystarczająco kompletny, aby się odtworzyć. Jaka klasa jest główna (String []) w? Czy klasy wewnętrzne ClassA, ClassB i ClassC lub oddzielne pliki źródłowe? Co ma wspólnego z tym MyObject? Kiedy mówisz, że zostanie załadowany w podanym przykładzie? Przydałoby się precyzyjne odwzorowanie zachowania, które opisujesz (a jak wspomina @SotiriosDelimanolis, jak mierzysz zachowanie, które opisujesz). –

Odpowiedz

4

Myślę, że to się dzieje podczas etapu weryfikacji, aby upewnić się, że ClassC jest podklasą ClassB, dla celów sprawdzania poprawności typu zwrotu.

Here, mówią:

Jeśli metoda zwraca typ referencyjny, musi to zrobić za pomocą areturn instrukcji, oraz typ zwracanej wartości musi być przypisanie kompatybilny (JLS §5.2) z deskryptorem zwrotnym (§ 4.3.3) metody .

Zobacz także this:

Weryfikacja (§4.10) zapewnia binarną reprezentację klasy lub interfejsu strukturalnie (§9.9). Weryfikacja może spowodować załadowanie dodatkowych klas i interfejsów (§5.3), ale nie musi powodować ich weryfikacji ani przygotowania.

+0

Yup, to jest dokładnie to. JVM musi załadować klasę A, która obejmuje załadowanie kodu metod do pamięci; Klasa A ma metodę, która zwraca ClassC, w ten sposób ładuje ClassC; Na koniec metoda zwraca obiekt klasy B, więc również klasa B musi zostać załadowana. Nie ma znaczenia, czy wywołać metodę, czy nie, metoda musi być już załadowana do pamięci, zanim będzie można ją wywołać, tak aby ładujący ładował wszystko, co każda metoda musi działać. Na przykład, gdyby miał inną metodę, która zwróciła ClassD, obie metody musiałyby być dostępne, a ClassD również musiałaby zostać załadowana. – Sekkuar

+0

@Sekkuar Myślę, że stanie się to podczas konwersji typu podczas powrotu metody. Wykona weryfikację wspomnianą w poście i wymaga od ClassB i ClassC przygotowania do ClassLoader. – gogog22510

+0

@Vlad Przechodziłem tylko część Linking i Ładowanie artykułu wcześniej i nie widziałem tej części ... Dziękuję za odpowiedź :) – gogog22510

Powiązane problemy