Table des matières
Class Loader
Hiérarchie de chargement des classes
Chargement de classe
Chargement dynamique des classes
Rechargement dynamique des classes
Conception de code de surcharge de classe
类加载器加载/重新加载示例
Maison Java javaDidacticiel Une introduction détaillée au chargement et au rechargement de classes dynamiques Java

Une introduction détaillée au chargement et au rechargement de classes dynamiques Java

Oct 17, 2018 pm 04:28 PM
java 反射

Cet article vous apporte une introduction détaillée au chargement et au rechargement de classes dynamiques Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Les classes peuvent être chargées et rechargées au moment de l'exécution en Java, même si ce n'est pas aussi simple qu'on le pense. Cet article expliquera quand et comment charger et recharger des classes en Java.
Vous pouvez vous demander si le chargement dynamique des classes fait partie de la réflexion Java ou du noyau Java. Quoi qu'il en soit, je l'ai mis dans Java Reflection faute d'un meilleur endroit pour le mettre.

Class Loader

Toutes les classes d'un programme Java sont chargées à l'aide de certaines sous-classes de java.lang.ClassLoader. Par conséquent, les classes chargées dynamiquement doivent également utiliser une sous-classe de java.lang.ClassLoader.
Lorsqu'une classe est chargée, les classes auxquelles elle fait référence seront également chargées. Le mode de chargement de classe se charge de manière récursive jusqu'à ce que toutes les classes requises soient chargées. Il se peut que ce ne soient pas toutes les classes de l'application. Les classes non référencées ne sont pas chargées tant qu'elles ne sont pas référencées.

Hiérarchie de chargement des classes

Le chargement des classes en Java est organisé en hiérarchies. Lorsque vous créez un ClassLoader autonome, vous devez fournir un ClassLoader parent. Si un ClassLoader est invité à charger une classe, il demandera à son ClassLoader parent de la charger. Si le chargeur de classe parent ne trouve pas la classe, le chargeur de classe enfant essaiera de la charger lui-même.

Chargement de classe

Les étapes permettant à un chargeur de classe de charger une classe sont les suivantes :

  1. Vérifiez si la classe a été chargée

  2. Si la classe n'est pas chargée, demandez au chargeur de classe parent de la charger

  3. Si le chargeur de classe parent ne peut pas charger la classe, essayez d'utiliser le chargeur de classe actuel pour le charger

Lorsque vous implémentez un chargeur de classe qui peut surcharger les classes, vous devez vous écarter un peu de cette séquence. Il ne faut pas demander au chargeur de classe parent de charger la classe à recharger. Nous en reparlerons plus tard.

Chargement dynamique des classes

Le chargement dynamique des classes est très simple. Tout ce que vous avez à faire est d’obtenir un ClassLoader et d’appeler sa méthode loadClass(). Un exemple est le suivant :

public class MainClass {

  public static void main(String[] args){

    ClassLoader classLoader = MainClass.class.getClassLoader();

    try {
        Class aClass = classLoader.loadClass("com.jenkov.MyClass");
        System.out.println("aClass.getName() = " + aClass.getName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }

}
Copier après la connexion

Rechargement dynamique des classes

Le rechargement dynamique des classes présente certains défis. Le chargeur de classe intégré à Java vérifie toujours si la classe a été chargée avant de la charger. Par conséquent, il n'est pas possible de recharger une classe à l'aide du chargeur de classe intégré à Java. Pour recharger une classe, vous devez implémenter votre propre sous-classe ClassLoader.
Même avec des sous-classes personnalisées de chargeurs de classes, il existe des défis. Toutes les classes chargées doivent être liées. Cette méthode est définitive et ne peut donc pas être remplacée par vos sous-classes ClassLoader. La méthode solve() ne permet pas à une instance ClassLoader de se lier deux fois à une classe. Par conséquent, chaque fois que vous devez recharger une classe, vous devez recréer une instance de la classe ClassLoader. Ce n'est pas impossible, mais il faut savoir quand concevoir la classe à recharger.

Conception de code de surcharge de classe

Comme mentionné ci-dessus, le ClassLoader qui charge la classe spécifiée ne peut pas être utilisé pour recharger cette classe. Par conséquent, un ClassLoader différent doit être utilisé pour charger cette classe. Cependant, cela crée de nouveaux problèmes.
Chaque classe chargée dans un programme Java est identifiée par son nom complet (nom du package + nom de la classe) et est chargée par une instance ClassLoader. Cela signifie que la classe MyObject chargée par le chargeur de classe A est différente de la même classe MyObject chargée par le chargeur de classe B. Le code de simulation est le suivant :

MyObject object = (MyObject)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");
Copier après la connexion

Notez comment la classe MyObject est référencée dans le code en tant que variable de type objet. Cela provoque le chargement de la classe MyObject par le chargeur de classe qui a déjà chargé le code résident de cette classe.
Si la fabrique d'objets myClassReloadingFactory charge MyObject à l'aide d'un chargeur de classe différent de celui du code résident, vous ne pouvez pas convertir la variable de type Object rechargée MyObject en type MyObject. Étant donné que les deux MyObjects sont chargés par des chargeurs de classes différents, ils sont considérés comme des classes différentes, même s'ils portent le même nom complet. Tenter de convertir la classe d'un objet en référence à une autre classe lèvera une ClassCastException.
Il est possible de contourner cette limitation, mais vous devez modifier votre code de deux manières :

  1. Utiliser l'interface comme type de variable et recharger uniquement la classe d'implémentation

  2. Utiliser la superclasse comme type de variable et recharger uniquement les sous-classes

Voici l'exemple de code :

MyObjectInterface object = (MyObjectInterface)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");
Copier après la connexion
MyObjectSuperclass object = (MyObjectSuperclass)
    myClassReloadingFactory.newInstance("com.jenkov.MyObject");
Copier après la connexion

Si le type de variable est une interface ou une superclasse, le code ci-dessus s'exécutera normalement et l'interface ou la superclasse ne sera pas rechargée lorsque l'implémentation ou la sous-classe sera rechargée.
Pour que le code ci-dessus fonctionne correctement, vous devez bien sûr implémenter votre propre chargeur de classe afin que l'interface ou la super classe soit chargée par sa classe parent. Lorsque votre chargeur de classe est invité à charger MyObject, il lui sera également demandé de charger l'interface MyObjectInterface ou la classe MyObjectSuperclass, car elles sont référencées en interne par la classe MyObject. Votre chargeur de classe doit déléguer le chargement de classe au même chargeur de classe qui a chargé l'interface ou la superclasse.

类加载器加载/重新加载示例

上文包含了很多内容。让我们看一下简单的示例。下面是一个简单的ClassLoader子类。注意它如何将类加载委托给它的父类,除了它想要重装的一个类之外。如果类加载被委派给了它的父类,它以后将不能被重新加载。记住,一个类只能被同一个ClassLoader实例加载。
如前所述,这只是一个示例,它显示了类加载器的行为的基本知识。这并不是一个你的类加载器的生产就绪的模板。你的类加载器可能并不仅限于一个类,可能是一个你想要重新加载的类的集合。此外,你也不能硬编码class path。

public class MyClassLoader extends ClassLoader{

    public MyClassLoader(ClassLoader parent) {
        super(parent);
    }

    public Class loadClass(String name) throws ClassNotFoundException {
        if(!"reflection.MyObject".equals(name))
                return super.loadClass(name);

        try {
            String url = "file:C:/data/projects/tutorials/web/WEB-INF/" +
                            "classes/reflection/MyObject.class";
            URL myUrl = new URL(url);
            URLConnection connection = myUrl.openConnection();
            InputStream input = connection.getInputStream();
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int data = input.read();

            while(data != -1){
                buffer.write(data);
                data = input.read();
            }

            input.close();

            byte[] classData = buffer.toByteArray();

            return defineClass("reflection.MyObject",
                    classData, 0, classData.length);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}
Copier après la connexion

下面是使用MyClassLoader的示例:

public static void main(String[] args) throws
    ClassNotFoundException,
    IllegalAccessException,
    InstantiationException {

    ClassLoader parentClassLoader = MyClassLoader.class.getClassLoader();
    MyClassLoader classLoader = new MyClassLoader(parentClassLoader);
    Class myObjectClass = classLoader.loadClass("reflection.MyObject");

    AnInterface2       object1 =
            (AnInterface2) myObjectClass.newInstance();

    MyObjectSuperClass object2 =
            (MyObjectSuperClass) myObjectClass.newInstance();

    //create new class loader so classes can be reloaded.
    classLoader = new MyClassLoader(parentClassLoader);
    myObjectClass = classLoader.loadClass("reflection.MyObject");

    object1 = (AnInterface2)       myObjectClass.newInstance();
    object2 = (MyObjectSuperClass) myObjectClass.newInstance();

}
Copier après la connexion

reflection.MyObject类是由自定义类加载器加载的。注意,它是如何继承一个超类、实现一个接口的。这只是为了这个例子。在你的代码中,只需要两个中的一个,继承超类或实现接口。

public class MyObject extends MyObjectSuperClass implements AnInterface2{
    //... body of class ... override superclass methods
    //    or implement interface methods
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Nombre parfait en Java Nombre parfait en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre parfait en Java. Nous discutons ici de la définition, comment vérifier le nombre parfait en Java ?, des exemples d'implémentation de code.

Weka en Java Weka en Java Aug 30, 2024 pm 04:28 PM

Guide de Weka en Java. Nous discutons ici de l'introduction, de la façon d'utiliser Weka Java, du type de plate-forme et des avantages avec des exemples.

Numéro de Smith en Java Numéro de Smith en Java Aug 30, 2024 pm 04:28 PM

Guide du nombre de Smith en Java. Nous discutons ici de la définition, comment vérifier le numéro Smith en Java ? exemple avec implémentation de code.

Questions d'entretien chez Java Spring Questions d'entretien chez Java Spring Aug 30, 2024 pm 04:29 PM

Dans cet article, nous avons conservé les questions d'entretien Java Spring les plus posées avec leurs réponses détaillées. Pour que vous puissiez réussir l'interview.

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Horodatage à ce jour en Java Horodatage à ce jour en Java Aug 30, 2024 pm 04:28 PM

Guide de TimeStamp to Date en Java. Ici, nous discutons également de l'introduction et de la façon de convertir l'horodatage en date en Java avec des exemples.

Programme Java pour trouver le volume de la capsule Programme Java pour trouver le volume de la capsule Feb 07, 2025 am 11:37 AM

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

Créer l'avenir : programmation Java pour les débutants absolus Créer l'avenir : programmation Java pour les débutants absolus Oct 13, 2024 pm 01:32 PM

Java est un langage de programmation populaire qui peut être appris aussi bien par les développeurs débutants que par les développeurs expérimentés. Ce didacticiel commence par les concepts de base et progresse vers des sujets avancés. Après avoir installé le kit de développement Java, vous pouvez vous entraîner à la programmation en créant un simple programme « Hello, World ! ». Une fois que vous avez compris le code, utilisez l'invite de commande pour compiler et exécuter le programme, et « Hello, World ! » s'affichera sur la console. L'apprentissage de Java commence votre parcours de programmation et, à mesure que votre maîtrise s'approfondit, vous pouvez créer des applications plus complexes.

See all articles