2017-10-10 15 views
1

Une classe java est initialisée une seule fois par JVM, lorsque la classe est chargée en premier. Et je pense que plus d'un thread peut essayer de charger la même classe simultanément. Comment une JVM gère-t-elle la contention de ceci? Y a-t-il un mécanisme pour l'empêcher, comme lock?Comment éviter que l'initialisation de classe simultanée ne se produise?

+0

'Une classe java est initialisé une seule fois par un jvm' - ce n'est pas vrai. L'instruction correcte devrait être 'Une classe java est initialisée une seule fois par classloader' – rkosegi

+1

http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2 –

Répondre

4

D'abord, la déclaration suivante est pas exacte:

Une classe java est initialisé une seule fois par une jvm

Une classe Java est initialisé une fois par classloader. Une instance JVM peut très bien avoir plusieurs chargeurs de classe, chacun chargeant la même classe séparément.

Et pour répondre à la question - oui, le classloader doit prendre un verrou pendant le chargement de la classe. Si, par exemple, vous jetez un oeil à la mise en œuvre de OpenJDK 9 de java.lang.ClassLoader, le chargement d'une classe finira par faire bouillir la méthode suivante (commentaire ajoutée pour souligner le verrouillage):

final Class<?> loadClass(Module module, String name) { 
    synchronized (getClassLoadingLock(name)) { // Note the locking here! 
     // First, check if the class has already been loaded 
     Class<?> c = findLoadedClass(name); 
     if (c == null) { 
      c = findClass(module.getName(), name); 
     } 
     if (c != null && c.getModule() == module) { 
      return c; 
     } else { 
      return null; 
     } 
    } 
} 
+1

La perspective de la JVM, "plusieurs chargeurs de classe, chacun chargeant la même classe séparément" sont juste plusieurs chargeurs de classe définissant des classes * différentes *, même s'ils peuvent avoir le même nom ou même le même code d'octet. Par conséquent, l'instruction "Une classe java n'est initialisée qu'une fois par jvm" est correcte et précise. De plus, le code cité ne fait qu'implémenter * loading * de la classe, pas l'initialisation *. Veiller à ce que l'initialisation ne se produise qu'une seule fois est toujours laissé à la JVM. – Holger