Vraag Wanneer laadt de JVM klassen?


Stel dat ik de volgende klasse heb:

class Caller {
  public void createSomething() {
    new Something();
  }
}

Zou deze regel uitvoeren:

static void main() {
   Class<?> clazz = Caller.class;
}

laat de JVM de klasse laden Something of wordt de class loading uitgesteld tot de methode createSomething() wordt genoemd?


19
2017-09-26 20:08


oorsprong


antwoorden:


Een klasse wordt alleen geladen als u informatie over die klasse nodig hebt.

public class SomethingCaller {
    public static Something something = null; // (1) does not cause class loading
    public static Class<?> somethingClass = Something.class; // (2) causes class loading

    public void doSomething() {
        new Something(); // (3) causes class loading
    }
}

De regels (2) en (3) zorgen ervoor dat de klasse wordt geladen. Het object Something.class bevat informatie (regel (2)) die alleen uit de klassendefinitie kan komen, dus u moet de klasse laden. De aanroep naar de constructor (3) vereist duidelijk de klassedefinitie. Evenzo voor elke andere methode in de klas.

Regel (1) zorgt er echter niet voor dat de klasse wordt geladen, omdat je eigenlijk geen informatie nodig hebt, het is gewoon een verwijzing naar een object.

EDIT: In je gewijzigde vraag, vraag je of het verwijzen naar Something.class de klasse laadt. Ja dat doet het. Het laadt de klasse pas als main () wordt uitgevoerd. Gebruik de volgende code:

public class SomethingTest {
    public static void main(String[] args) {
        new SomethingCaller();
    }
}

public class SomethingCaller {
    public void doSomething() {
        Class<?> somethingClass = Something.class;
    }
}

public class Something {}

Deze code zorgt er niet voor dat de Something.class wordt geladen. Als ik echter doSomething () aanroept, wordt de klasse geladen. Om dit te testen, maakt u de bovenstaande klassen, compileert u ze en verwijdert u het Something.class-bestand. De bovenstaande code crasht niet met een ClassNotFoundException.


21
2017-09-26 21:32



Ja, dat zorgt ervoor dat de klasse wordt geladen wanneer de klasse met de File.class referentie is geladen. De enige manier om dit niet te doen, is door te verwijzen naar een klasse door te reflecteren. Dan kun je bepalen wanneer het is geladen.


2
2017-09-26 20:10



Als u aan deze prestatievereisten voldoet, kunt u overwegen een aangepast ClassLoader-object te schrijven. Hiermee kun je klassen uit het geheugen verwijderen als ze niet meer nodig zijn.

Je wilt het loadClass, findClass en waarschijnlijk de defineClass methoden in de ClassLoader class, overbelasting van de load en defineClass vinden en gebruiken in de implementatie. Een google-zoekopdracht voor het schrijven van aangepaste klasse-laders zal veel voorbeeldcodes onthullen om dit te doen, maar in principe ga je de klasseresultaten opslaan in een kaart (class-naam in Class), dan voorzien van een aantal callback-mechanismen om geladen klassen uit je cache te verwijderen wanneer ze niet nodig zijn.

succes.


-1
2017-09-26 20:27