Dépendance au temps de compilation vs au temps d'exécution-Java


Quelle est la différence entre les dépendances à la compilation et à l'exécution en Java? Il est lié au chemin de classe, mais en quoi diffèrent-ils?

Author: ROMANIA_engineer, 2010-11-24

6 answers

  • Dépendance à la compilation : Vous avez besoin de la dépendance dans votre CLASSPATH pour compiler votre artefact. Ils sont produits parce que vous avez une sorte de" référence " à la dépendance codée en dur dans votre code, comme appeler new pour une classe, étendre ou implémenter quelque chose (directement ou indirectement), ou un appel de méthode utilisant la notation directe reference.method().

  • Dépendance d'exécution : Vous avez besoin de la dépendance dans votre CLASSPATH pour exécuter votre artefact. Ils sont produits parce que vous exécutez du code qui accède à la dépendance (soit de manière codée en dur, soit par réflexion ou autre).

Bien que la dépendance à la compilation implique généralement une dépendance à l'exécution, vous pouvez avoir une dépendance à la compilation uniquement. Ceci est basé sur le fait que Java ne lie que les dépendances de classe lors du premier accès à cette classe, donc si vous n'accédez jamais à une classe particulière au moment de l'exécution car un chemin de code n'est jamais parcouru, Java ignorera à la fois la classe et ses dépendances.

Exemple de ceci

Dans C.java (génère C.class):

package dependencies;
public class C { }

Dans A.java (génère A.class):

package dependencies;
public class A {
    public static class B {
        public String toString() {
            C c = new C();
            return c.toString();
        }
    }
    public static void main(String[] args) {
        if (args.length > 0) {
            B b = new B();
            System.out.println(b.toString());
        }
    }
}

Dans ce cas, A a une dépendance au moment de la compilation sur C à travers B, mais il n'aura une dépendance au moment de l'exécution sur C que si vous passez certains paramètres lors de l'exécution de java dependencies.A, car la JVM n'essaiera de résoudre la dépendance de B sur C Cette fonctionnalité vous permet de fournir au moment de l'exécution uniquement les dépendances des classes que vous utilisez dans vos chemins de code, et ignorez les dépendances du reste des classes dans l'artefact.

 59
Author: gpeche, 2013-05-16 18:36:03

Un exemple facile est de regarder une api comme l'api servlet. Pour compiler vos servlets, vous avez besoin de l'api servlet.jar, mais au moment de l'exécution, le conteneur de servlet fournit une implémentation d'api de servlet, vous n'avez donc pas besoin d'ajouter de servlet-api.jar à votre chemin de classe d'exécution.

 26
Author: Martin Algesten, 2015-06-15 20:07:58

Le compilateur a besoin du bon chemin de classe pour compiler les appels vers une bibliothèque (dépendances au moment de la compilation)

La JVM a besoin du bon chemin de classe pour charger les classes dans la bibliothèque que vous appelez (dépendances d'exécution).

Ils peuvent être différents de plusieurs façons:

1) si votre classe C1 appelle la classe de bibliothèque L1, et L1 appelle la classe de bibliothèque L2, alors C1 a une dépendance d'exécution sur L1 et L2, mais seulement une dépendance au moment de la compilation sur L1.

2) si votre classe C1 instancie dynamiquement une interface I1 en utilisant la classe.forName() ou un autre mécanisme, et la classe d'implémentation pour l'interface I1 est la classe L1, alors C1 a une dépendance d'exécution sur I1 et L1, mais seulement une dépendance de compilation sur I1.

Autres dépendances "indirectes" qui sont les mêmes pour la compilation et l'exécution:

3) votre classe C1 étend la classe de bibliothèque L1, et L1 implémente l'interface I1 et étend la classe de bibliothèque L2: C1 a une dépendance à la compilation sur L1, L2 et I1.

4) votre classe C1 a une méthode foo(I1 i1) et une méthode bar(L1 l1) où I1 est une interface et L1 est une classe qui prend un paramètre qui est l'interface I1: C1 a une dépendance à la compilation sur I1 et L1.

Fondamentalement, pour faire quelque chose d'intéressant, votre classe doit s'interfacer avec d'autres classes et interfaces dans le chemin de classe. Le graphe de classe/interface formé par cet ensemble d'interfaces de bibliothèque donne la chaîne de dépendances au moment de la compilation. Bibliothèque les implémentations donnent la chaîne de dépendances à l'exécution. Notez que la chaîne de dépendances à l'exécution dépend de l'exécution ou échoue: si l'implémentation de L1 dépend parfois de l'instanciation d'un objet de la classe L2, et que cette classe n'est instanciée que dans un scénario particulier, il n'y a pas de dépendance sauf dans ce scénario.

 21
Author: Jason S, 2010-11-24 23:12:38

Java ne lie rien au moment de la compilation. Il vérifie uniquement la syntaxe en utilisant les classes correspondantes qu'il trouve dans le CHEMIN de CLASSE. Ce n'est qu'à l'exécution que tout est assemblé et exécuté en fonction du CHEMIN de classe à ce moment-là.

 10
Author: JOTN, 2010-11-24 20:02:06

Les dépendances Compiletime ne sont que les dépendances (autres classes) que vous utilisez directement dans la classe que vous compilez. Les dépendances d'exécution couvrent à la fois les dépendances directes et indirectes de la classe que vous exécutez. Ainsi, les dépendances d'exécution incluent les dépendances des dépendances et toutes les dépendances de réflexion comme les noms de classe que vous avez dans un String, mais qui sont utilisées dans Class#forName().

 9
Author: BalusC, 2010-11-24 20:03:24

Pour Java, la dépendance au moment de la compilation est la dépendance de votre code source. Par exemple, si la classe A appelle une méthode de la classe B, alors A dépend de B au moment de la compilation car A doit connaître B (type de B) à compiler. L'astuce ici devrait être la suivante: Le code compilé n'est pas encore un code complet et exécutable. Il comprend des adresses remplaçables (symboles, métadonnées) pour les sources qui ne sont pas encore compilées ou existantes dans des fichiers jar externes. Lors de la liaison, ces adresses doivent être remplacées par adresses réelles dans la mémoire. Pour le faire correctement, des symboles/adresses corrects doivent être créés. Et cela peut être fait avec le type de la classe (B). Je crois que c'est la dépendance principale au moment de la compilation.

La dépendance d'exécution est plus liée au flux de contrôle réel. Il implique des adresses mémoire réelles. C'est une dépendance que vous avez lorsque votre programme est en cours d'exécution. Vous avez besoin de détails de classe B ici comme les implémentations, pas seulement les informations de type. Si la classe n'existe pas, alors vous aurez obtenez RuntimeException et JVM quittera.

Les deux dépendances, généralement et ne devraient pas, circulent dans la même direction. C'est une question de conception OO cependant.

En C++, la compilation est un peu différente (pas juste dans le temps) mais elle a aussi un éditeur de liens. Donc, le processus pourrait être pensé comme Java je suppose.

 1
Author: zgulser, 2016-02-02 08:08:11