La différence entre le contexte du thread classe chargeur et chargeur de classe normale
Quelle est la différence entre un contexte du thread chargeur de classe et de classe normale du chargeur?
Qui est, si Thread.currentThread().getContextClassLoader()
et getClass().getClassLoader()
différents retour chargeur de classe d'objets, dont l'un sera utilisé?
OriginalL'auteur abracadabra | 2009-11-20
Vous devez vous connecter pour publier un commentaire.
Chaque classe va utiliser son propre classloader pour charger d'autres classes. Donc, si
ClassA.class
référencesClassB.class
puisClassB
doit être dans le classpath du chargeur de classe deClassA
, ou de ses parents.Le contexte du thread chargeur de classe est le chargeur de classe actuel pour le thread courant. Un objet peut être créé à partir d'une classe dans
ClassLoaderC
et ensuite transmis à un fil détenue parClassLoaderD
. Dans ce cas, l'objet doit utiliserThread.currentThread().getContextClassLoader()
directement, s'il veut charger les ressources qui ne sont pas disponibles sur son propre classloader.ClassB
doit être dans le classpath deClassA
's loader (ouClassA
's du chargeur parents)? N'est-il pas possible pourClassA
's chargeur pour remplacerloadClass()
, tel qu'il peut charger avec succèsClassB
même lorsqueClassB
n'est pas sur son chemin de classe?En effet, tous les chargeurs de classe ont un classpath. Quand a écrit "ClassB doit être dans le classpath du chargeur de classe ClassA", je voulais dire "ClassB doit chargeable par le chargeur de classe de ClassA". 90% du temps, ils signifient la même chose. Mais si vous n'êtes pas à l'aide d'une URL en fonction de chargeur de classe, seul le deuxième cas, c'est vrai.
Que signifie le fait de dire que "
ClassA.class
référencesClassB.class
"?Lorsque ClassA a une instruction import pour ClassB, ou si il existe une méthode de ClassA qui a une variable locale de type ClassB. Qui va déclencher ClassB à charger, si ce n'est pas déjà chargé.
Je pense que mon problème est lié à ce sujet. Que pensez-vous de ma solution? Je sais que ce n'est pas un bon modèle, mais je n'ai pas d'autres idée de comment résoudre ce problème: stackoverflow.com/questions/29238493/...
OriginalL'auteur David Roussel
Il y a un article sur javaworld.com qui explique la différence
=> Qui ClassLoader devriez-vous utiliser
(1)
(2) de la même source:
la solution de contournement proposée est tout à fait le contraire de ce que vous dites à la fin. Ce n'est pas le parent
bootstrap
chargeur de classe étant définie comme le contexte de la classe loader mais l'enfantsystem
classpath chargeur de classe que leThread
est mis en place avec. LeJNDI
classes sont alors assurez-vous de l'utilisationThread.currentThread().getContextClassLoader()
à la charge de la JNDI de la mise en œuvre des classes disponibles dans le classpath."Normal J2SE délégation ne fonctionne pas", je peux savoir pourquoi cela ne fonctionne pas? Parce que le Bootstrap chargeur de classe ne peut charger que de la classe de rt.jar et impossible de charger la classe à partir de l'application -classpath? Droit?
OriginalL'auteur Timour
Cela ne répond pas à la question d'origine, mais que la question est très bien classé et liés pour toute
ContextClassLoader
requête, je pense qu'il est important de répondre à la question connexe de la quand la classe de contexte chargeur doit être utilisé. Réponse courte: ne jamais utiliser le contexte de la classe loader! Mais mis àgetClass().getClassLoader()
lorsque vous appelez une méthode qui manque unClassLoader
paramètre.Lorsque le code d'une classe demande de charger une autre classe, le bon chargeur de classe à utiliser est le même chargeur de classe en tant qu'appelant classe (c'est à dire,
getClass().getClassLoader()
). C'est la façon dont les choses fonctionnent à 99,9% du temps parce que c'est ce que la JVM ne se la première fois que vous construisez une instance d'une classe nouvelle, appeler une méthode statique, ou d'accéder à un champ statique.Lorsque vous souhaitez créer une classe à l'aide de réflexion (comme lors de la désérialisation ou le chargement d'un configurables de la classe nommée), la bibliothèque qui fait la réflexion devrait toujours demander l'application qui le chargeur de classes à utiliser, en recevant le
ClassLoader
comme un paramètre de l'application. L'application (qui connaît toutes les classes qui ont besoin de la construction) devrait passergetClass().getClassLoader()
.De toute autre manière à obtenir un chargeur de classe est incorrect. Si une bibliothèque utilise des hacks comme
Thread.getContextClassLoader()
,sun.misc.VM.latestUserDefinedLoader()
, ousun.de réfléchir.De la réflexion.getCallerClass()
c'est un bug causé par une carence dans l'API. Fondamentalement,Thread.getContextClassLoader()
n'existe que parce que celui qui a conçu leObjectInputStream
API oublié d'accepter laClassLoader
comme paramètre, et cette erreur a hanté la communauté de Java à ce jour.Cela dit, de nombreuses de nombreuses classes du JDK utiliser l'un des quelques hacks de deviner certaines chargeur de classe à utiliser. Certains utilisent le
ContextClassLoader
(qui échoue lorsque vous exécutez des applications différentes sur un shared pool de threads, ou lorsque vous quittez leContextClassLoader null
), certains à pied de la pile (qui échoue lorsque le direct de l'appelant de la classe est elle-même une bibliothèque), certains utilisent le système de chargeur de classe (ce qui est bien, aussi longtemps qu'il est documenté à utiliser uniquement des classes dans leCLASSPATH
) ou classe de bootstrap loader, et certains utilisent un imprévisible combinaison des techniques ci-dessus (qui ne rend les choses plus confuses). Cela a entraîné beaucoup de pleurs et des grincements de dents.Lors de l'utilisation d'une telle API, d'abord, essayez de trouver une surcharge de la méthode qui accepte le chargeur de classe en tant que paramètre. Si il n'est pas judicieux de la méthode, puis essayez de définir le
ContextClassLoader
avant l'appel d'API (et de le rétablir par la suite):OriginalL'auteur yonran
L'ajout de @David Roussel réponse, les classes peuvent être chargées par plusieurs chargeurs de classe.
Permet de comprendre comment chargeur de classe œuvres.
De javin paul blog dans javarevisited :
ClassLoader
suit trois principes.Délégation principe
Bootstrap chargeur de classe est responsable du chargement standard JDK fichiers de classe de rt.jar et il est le parent de tous les chargeurs de classe en Java. Classe de Bootstrap loader n'ont pas de parents.
Extension du chargeur de classe délégués de classe de la demande de chargement de son parent, de démarrage et en cas d'échec, les charges de la classe forme jre/lib/ext de répertoire ou de tout autre répertoire pointé par java.ext.dirs système de la propriété
Système ou de l'Application du chargeur de classe et il est responsable du chargement de l'application spécifique des classes à partir de la variable d'environnement CLASSPATH, -classpath ou -cp option de ligne de commande, la Classe-attribut de Chemin d'accès de fichier de Manifeste à l'intérieur du POT.
Application du chargeur de classe est un enfant de Extension du chargeur de classe et sa mise en œuvre par
sun.misc.Launcher$AppClassLoader
classe.REMARQUE: Sauf classe de Bootstrap loader, qui est mis en œuvre dans la langue maternelle principalement en C, l'ensemble de la classe Java chargeurs sont mis en œuvre à l'aide de
java.lang.ClassLoader
.Visibilité Principe
Unicité Principe
OriginalL'auteur Ravindra babu