12
votes

Le chargeur de classe Java est-il garanti de ne pas charger des classes qui ne sont pas utilisées?

Y a-t-il une garantie que (le système par défaut, le système de classe Java ne tente pas de charger des classes qui ne sont pas mentionnées dans le code étant exécuté? Quelques exemples de ce que je veux dire:

  • J'utilise un framework.jar que je sais contenir des références à un autre la bibliothèque.jar s classes de la bibliothèque.jar, mais j'utilise seulement une telle partie du cadre qui ne contient pas ces références. Est-il sûr de laisser bibliothèque.jar out?
  • Les blocs statiques sont exécutés lorsqu'une classe est chargée d'abord. Si aucun code d'exécution ne contient de références à une classe spécifique, est-ce que c'est sûr que le bloc statique n'est pas exécuté?

    Test rapide Il semble fonctionner comme supposé ci-dessus, et il n'aurait pas fort de sens de charger de toute façon une utilisation de classes inutilisées, mais y a-t-il une garantie à ce sujet?

    addition: Il semble que mes "blocs statiques sont exécutés lorsqu'une classe est chargée première" La déclaration ci-dessus est quelque peu incorrecte. C'est définitivement possible de charger les classes (une chose) sans courir eux (autre chose). Donc, je suis intéressé par les deux cas; Garanties sur les classes ne reçoivent pas chargé et ne pas obtenir courir .


0 commentaires

7 Réponses :


8
votes

Il n'y a pas de telles garanties 1 WRT le chargement des classes.

Cependant, vous êtes assuré que les blocs statiques ne seront pas gérés prématurément. Les événements qui déclenchent la classe initialisation sont spécifiés dans JLS 12.4 .1 .

Un type de classe ou d'interface T sera initialisé immédiatement avant la première occurrence de l'une des opérations suivantes:

  • t est une classe et une instance de T est créée.
  • t est une classe et une méthode statique déclarée par T est invoquée.
  • Un champ statique déclaré par T est attribué.
  • Un champ statique déclaré par T est utilisé et que le champ n'est pas une variable constante (§4.12.4).
  • T est une classe de niveau supérieur et une déclaration d'affirmation (§14.10) lexiquement imbriquée sous t est exécutée.

    1 - on observe que la génération de courant Les implémentations Java ne chargent pas inutilement les classes, mais ce n'est pas une garantie. Les seules garanties sont ce qu'elle a écrit dans les spécifications officielles.


0 commentaires

1
votes

Je ne pense pas qu'il y ait une telle garantie. D'une part, j'ai vu des scanners de code qui font des choses comme la transformation des annotations de hiérarchies / bocaux d'emballage entiers lors du démarrage de l'application; ils violeraient cette hypothèse immédiatement.

Pourquoi cela compte-t-il? Vous êtes généralement après une chargement de système hautement contrôlable de sorte que tout ce qui importerait serait quelque part où vous voudriez de toute façon ...


0 commentaires

1
votes

La chose qui tire dans des classes est les références à partir du code octet Java (qui peut encore tirer dans d'autres classes). Si les classes que vous exécutez, n'avez aucune référence à la classe X, elle ne sera pas chargée.

Notez cependant qu'il y a de nouvelles façons de s'inscrire par exemple. services par Meta-Inf. Ces classes doivent aussi être chargées.

Vous pouvez toujours fonctionner avec "-verbose" pour voir les classes lorsqu'elles se chargent - la commande montre clairement qu'elles sont chargées en cas de besoin.


1 commentaires

Afaik, ce n'est pas seulement la "référence" qui compte ici, mais aussi l'utilisation. Tant qu'une classe n'est pas utilisée (c'est-à-dire référencée dans une instruction de bytecode exécutant), elle n'est pas chargée. Bien sûr, cela n'est pas garanti par la spécification mais aucun JVM de soi-même se comporte ainsi.



4
votes

Le java Spécification états < / p>

Le processus de chargement est mis en œuvre par le chargeur de classe et son sous-classes. Différents sous-classes de Le chargeur de classe peut mettre en œuvre différents Politiques de chargement. En particulier, un chargeur de classe peut Représentations binaires de cache de classes et interfaces, préparez-les basé sur l'utilisation attendue ou charger un groupe de classes connexes ensemble.

Le chargeur de classe est donc libre de préférer les fichiers de classe.

Un type de classe ou d'interface T sera initialisé immédiatement avant le première occurrence de l'un des Suivant:

  • t est une classe et une instance de T est créée.
  • t est une classe et une méthode statique déclarée par T est invoquée.
  • Un champ statique déclaré par T est attribué.
  • Un champ statique déclaré par T est utilisé et la référence au champ n'est pas une constante de temps de compilation (§15.28). Les références aux constantes de compilation doivent être résolues lors de la compilation d'une copie de la valeur constante de la compilation, de sorte que les utilisations d'un tel champ ne provoquent jamais l'initialisation.

    Les blocs statiques ne seront exécutés que lorsque la classe est utilisée pour la première fois.


1 commentaires

+1 pour «Préfichez-les sur l'utilisation attendue, ou chargez un groupe de classes associées». Donc, il n'y a certainement aucune garantie de ne rien charger.



1
votes

Si vous n'utilisez pas de réflexion, vous pouvez vérifier statiquement les classes utilisées à l'aide d'un outil de suppression de code mort, tel que Proguard . Il analysera votre code et déterminera toutes les classes utilisées. Sur la base de cela, il supprime le code inutilisé, y compris le code inutilisé dans les bibliothèques.

Si votre code ou vos bibliothèques utilise la réflexion pour charger des classes, vous devez exécuter un test de couverture complète de votre application et enregistrer toutes les classes chargées, que vous demandez à PROGUARD de conserver.


1 commentaires

Je pense que Joonas Project a une dépendance sur le cadre.jar qui a une dépendance à la bibliothèque.jar. Joonas croit néanmoins que son projet ne dépend pas de la bibliothèque.jar. PROGUARD peut-il vraiment vérifier que l'affirmation?



0
votes

Il n'y a pas de garantie de telles garanties car d'autres affiches ont mentionné. Mais votre question et votre préoccupation ne vous suivent pas. Pour que vous quittiez la bibliothèque.jar, vous n'avez pas besoin de telles garanties.

Il existe un certain nombre de cadres découvrant la présence ou l'absence d'autres cadres pendant l'exécution. Ex: La journalisation des communes découvre un tas d'autres cadres. Spring Web Flow découvre ce que le cadre de script est (est-il OGOnL par exemple) pendant l'exécution. Ces cadres sont évidemment compilés à l'aide de tous les cadres dépendants, mais ils n'ont pas à exister pendant l'exécution.

Il est donc parfaitement acceptable de quitter la bibliothèque.jar pendant l'exécution.


0 commentaires

0
votes

Oui.

Pensez à ce qui suit. Si vous ajoutez le code suivant à ce bibliothèque.jar Classe: xxx

Ce code ne sera pas chargé automatiquement par le système par défaut, car aucun du code existant a une référence ou connaît la classe Shutdown , ni un moyen de le charger, et le chargeur de classe Java ne va pas simplement essayer de charger des classes aléatoires du pot. < / p>

La manière dont les classes sont chargées sont décrites dans les réponses précédentes, si vous les examinez soigneusement, aucun d'entre eux n'incluent pas un "s'il y a une classe dans le pot, il serait chargé" de une sorte.


1 commentaires

Je pense que vous vous confondez la chargement de classe et l'initialisation de la classe.