当前位置:网站首页>JVM entry Door (1)
JVM entry Door (1)
2022-06-26 18:06:00 【Interview Java 365】
JVM
Qu'est - ce queJVM
JVMNom completJava Virtual Machine,JavaLa machine virtuelle fonctionne sur le système d'exploitation,Ne pas interagir directement avec le matériel,Au milieu, le système d'exploitation nous aide à interagir avec le matériel

JVML'architecture de
Pour comprendreJAVAComment le fichier est exécuté,Il faut d'abord comprendre toutJVML'architecture de

Zone jaune:Représente tous les Threads partagés,Présence de déchets recyclés.
Zone grise:Représente un thread privé,Moins de mémoire.
Chargeur de classe
Qu'est - ce qu'un chargeur de classe
Le chargeur de classe compileraclassLe fichier Bytecode est chargé en mémoire,Et convertit cette mémoire en une structure de données d'exécution dans la zone de méthode,Notez que le chargeur de classe n'est responsable que declassChargement des fichiers,Quant à savoir si elle peut fonctionner, elle doit être effectuée parExecution EnginDécide que.
Comme suit,UnCar.classBinaires,Initialisation d'un modèle de classe par le chargeur de classe,Plus tard, nous instancions chaquecarObjet instance.

Type de chargeur de classe
Les chargeurs de classe sont divisés en quatre types ,Chargeur racine、Chargeur de classe d'extension、Chargeur de classe d'application、Chargeur personnalisé, Qu'est - ce que ces quatre types de chargeurs ont à voir avec ?

public static void main(String[] args) {
Car car = new Car("Cherie.QQ");
Class<? extends Car> carClass = car.getClass();
// AccèsclassChargeur pour [email protected]
System.out.println(carClass.getClassLoader());
// Obtenir le courantclass Chargeur parent du chargeur de classe [email protected]
System.out.println(carClass.getClassLoader().getParent());
// Obtenir le courantclass Le chargeur parent du chargeur de classe null
System.out.println(carClass.getClassLoader().getParent().getParent());
}
À partir des codes ci - dessus ,Car Le chargeur de classe est le chargeur de classe d'application , Et le chargeur parent est un chargeur de classe étendu , Et le chargeur parent du chargeur de classe d'extension est null,null Ça prouve qu'il n'y a pas de chargeur ?Ce n'est pas,C'estnull Prouver que c'est le chargeur racine , En fait, le langage de mise en oeuvre est C/C++,JVM Les programmeurs ne sont pas autorisés à obtenir cette classe ,C'est pour ça quenull.
Chargeur de classe personnalisé
Pourquoi un chargeur de classe personnalisé est - il nécessaire
Il existe trois types de chargeurs de classe d'application dans le système. 、Chargeur de classe d'extension、 Le chargeur racine devrait répondre aux besoins quotidiens de développement , Pourquoi un chargeur de classe personnalisé est - il nécessaire? ? Les scénarios suivants peuvent être utilisés
Le code byte de certaines bibliothèques de classe de base de l'entreprise peut être chiffré , Un chargeur personnalisé est nécessaire pour déchiffrer les octets chiffrés ,Puis charger en mémoire.
Le fichier Bytecode peut provenir du réseau 、Base de données、 Des scénarios tels que le disque dur nécessitent un chargeur de classe personnalisé pour charger le fichier Bytecode .
Résoudre les conflits de version dépendants entre plusieurs modules d'un projet .
Comment puis - je utiliser un chargeur de classe personnalisé? ?
L'idée centrale est en deux étapes
SuccessionClassLoaderCatégorie
RéécriturefindClassMéthodes
public class CustomClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
// Spécifiez le chemin de chargement de la classe name Est le nom de classe entièrement qualifié de la classe spécifique
String cname = "E:\\ideaProject\\demo\\src\\main\\java\\" + name.replace('.', '/') + ".class";
// Accèsclass Tous les tableaux d'octets de la classe
byte[] classBytes = Files.readAllBytes(Paths.get(cname));
Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
if (cl == null) {
throw new ClassNotFoundException(name);
}
return cl;
} catch (IOException e) {
System.out.print(e);
throw new ClassNotFoundException(name);
}
}
}
Implémenter n'importe quelle classe de chargement
public class Car {
private String name;
public Car(String name) {
this.name = name;
}
public void getCar(){
System.out.println("Car is Name "+getName());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
InCar Exécution du dossier pour la classe javac Car.javaLes ordres,Compilation manuelle,GénérerCar.classAprès le document,SupprimerCar.javaConservation des documentsCar.classDocumentation, Ceci est fait pour empêcher le chargeur d'application de charger CarCatégorie.
Écrire la classe d'appel du chargeur de classe
public class ClassLoaderTest {
public static void main(String[] args) {
try {
ClassLoader loader = new CustomClassLoader();
// ChargementCarCatégorie
// Lorsque d'autres chargeurs ne peuvent pas être chargés dans cette classe , Le chargeur personnalisé sera appelé findClassMéthodes
Class<?> c = loader.loadClass("com.example.demo.testjvm.Car");
System.out.println("Chargeur de classe==="+c.getClassLoader());
// Méthode d'exécution de la réflexion
// Le constructeur a des paramètres qui sont construits ici
Constructor<?> constructor = c.getDeclaredConstructor(String.class);
// Objet de construction
Object o = constructor.newInstance("BMW");
Method m = c.getMethod("getCar");
m.invoke(o);
} catch (Throwable e) {
System.out.println(e);
}
}
}
Résultats de la mise en œuvre

Mécanisme de délégation parentale
Chargeur de classe personnalisé ci - dessus , Appelé lors du chargement de la classe loadClassMéthodes, Nous pouvons voir la mise en œuvre concrète de cette approche
// ClassLoaderClasseloadClassMéthodes
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// Vérifier si cette classe a été chargée, Assurez - vous qu'il n'y a pas de chargement répété
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// Le chargeur parent est chargé chaque fois qu'il existe un chargeur parent ,C'est récursif.
if (parent != null) {
c = parent.loadClass(name, false);
} else {
// Sortie récursive
// Siparent- Oui.null Représente le chargeur racine , L'équivalent de toutes les classes trouvera le chargeur racine essayant de charger
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
// Si le chargeur parent ne charge pas, Alors le chargeur actuel essaie de charger (Chargeur de classe d'extension、Chargeur de classe d'application、Chargeur personnalisé)
if (c == null) {
// Si la classe n'a jamais été trouvée, appelez le chargeur actuel dans l'ordre findClassMéthodes
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
D'après le code ci - dessus, Lorsqu'un chargeur reçoit une demande de chargement de classe , Je ne vais pas charger cette classe moi - même , Au lieu de cela, la classe est déléguée à la classe mère pour compléter , C'est le cas pour chaque chargeur de classe hiérarchique , Par conséquent, toutes les demandes de chargement de classe passent par le chargeur racine , Ce n'est que lorsque le chargeur parent ne peut pas charger cette classe , Le chargeur actuel essaie de charger lui - même ,C'est la délégation parentale.,En résumé,Délégation vers le Haut、Vers le bas.

Pourquoi est - ce nécessaire?? Juste pour assurer la sécurité ,Voici quelques exemples:, Nous savons que le chargeur racine est chargé rt.jarLes classes à l'intérieur,Il est chargé.String、ObjectAttends, attends.jdkClasse autonome, Si nous définissons le même nom de paquet dans le Code String La classe permet - elle au chargeur racine de personnaliser StringEt la classe??
// Définir le même nom de paquet
package java.lang;
// Définir le même nom de classe
public class String {
public String toString() {
return "hello";
}
public static void main(String[] args) {
// Ce qui est appelé ici est son propre StringCatégorie
String str = new String();
str.toString();
}
}
Résultats de la mise en œuvre

C'est le principe de la délégation parentale , Lorsque le chargeur de classe d'application reçoit une demande de chargement pour cette classe , L'ordre de délégation vers le haut est
Chargeur de classe d'application—>Chargeur de classe d'extension---->Chargeur racine
Le chargeur racine essaie de charger cette classe , Trouvé avec le même nom que le paquet StringCatégorie, Donc le chargeur racine a été chargé avec succès , Chargé ou rt.jarDansStringCatégorie, L'avantage est que jvm Exécuter une classe importante d'autres chargeurs n'ont pas la possibilité de charger à nouveau , L'implantation de codes de danger peut être évitée dans une certaine mesure .
边栏推荐
猜你喜欢

物联网协议的王者:MQTT

分页查询、JOIN关联查询优化

MySQL的MVCC机制详解

【代码随想录-动态规划】T583、两个字符串的删除操作

必须要掌握的面试重点——索引和事务(附讲B-树与B+树)

Vscode usage - Remote SSH configuration description

Applet setting button sharing function

Ethereum技术架构介绍

DoS及攻擊方法詳解

No manual prior is required! HKU & Tongji & lunarai & Kuangshi proposed self supervised visual representation learning based on semantic grouping, which significantly improved the tasks of target dete
随机推荐
【代码随想录-动态规划】T583、两个字符串的删除操作
wechat_微信小程序中解决navigator进行页面跳转并传递参数问题
pycharm的plt.show()如何保持不关闭
深入理解MySQL锁与事务隔离级别
14《MySQL 教程》INSERT 插入数据
DoS及攻擊方法詳解
让torch.cuda.is_available()从false变成true的一点经验
RSA加密解密详解
二分查找-2
陈强:阿里千亿级大规模数字商业知识图谱助力业务增长
map和filter方法对于稀缺数组的处理
【Unity】在Unity中使用C#执行外部文件,如.exe或者.bat
Digital signature standard (DSS)
How pycharm modifies multiline annotation shortcuts
行锁与隔离级别案例分析
Preparing for the Blue Bridge Cup and ccf-csp
LM06丨仅用成交量构造抄底摸顶策略的奥秘
[code Capriccio - dynamic planning] t583. Deleting two strings
博云,站在中国容器潮头
MYSQL的下载与配置 mysql远程操控