zoukankan      html  css  js  c++  java
  • JVM类加载

    JVM class文件格式

    • 魔法数 CAFE BABE
    • 编译器版本号
    • Constant count
    • Constant pool
    • access flag
    • this class
    • super class
    • interface count
    • interfaces
    • field count
    • fields
    • method count
    • methods
    • attribute count
    • attributes

    源码:User.java

    package com.wod.dao;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope("prototype")
    public class User {
      @Value("lisi")
      String username;
      String password;
    }
    

    class:User.class

    Classfile /d:/work/develop/juc_test/target/classes/com/wod/dao/User.class
      Last modified 2020-6-20; size 562 bytes
      MD5 checksum 27726ee8ded9222615d43ded38db4561
      Compiled from "User.java"
    public class com.wod.dao.User
      minor version: 0
      major version: 52
      flags: ACC_PUBLIC, ACC_SUPER
    Constant pool:
       #1 = Class              #2             // com/wod/dao/User
       #2 = Utf8               com/wod/dao/User
       #3 = Class              #4             // java/lang/Object
       #4 = Utf8               java/lang/Object
       #5 = Utf8               username
       #6 = Utf8               Ljava/lang/String;
       #7 = Utf8               RuntimeVisibleAnnotations
       #8 = Utf8               Lorg/springframework/beans/factory/annotation/Value;
       #9 = Utf8               value
      #10 = Utf8               lisi
      #11 = Utf8               password
      #12 = Utf8               <init>
      #13 = Utf8               ()V
      #14 = Utf8               Code
      #15 = Methodref          #3.#16         // java/lang/Object."<init>":()V
      #16 = NameAndType        #12:#13        // "<init>":()V
      #17 = Utf8               LineNumberTable
      #18 = Utf8               LocalVariableTable
      #19 = Utf8               this
      #20 = Utf8               Lcom/wod/dao/User;
      #21 = Utf8               SourceFile
      #22 = Utf8               User.java
      #23 = Utf8               Lorg/springframework/stereotype/Component;
      #24 = Utf8               Lorg/springframework/context/annotation/Scope;
      #25 = Utf8               prototype
    {
      java.lang.String username;
        descriptor: Ljava/lang/String;
        flags:
        RuntimeVisibleAnnotations:
          0: #8(#9=s#10)
    
      java.lang.String password;
        descriptor: Ljava/lang/String;
        flags:
    
      public com.wod.dao.User();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=1, locals=1, args_size=1
             0: aload_0
             1: invokespecial #15                 // Method java/lang/Object."<init>":()V
             4: return
          LineNumberTable:
            line 16: 0
          LocalVariableTable:
            Start  Length  Slot  Name   Signature
                0       5     0  this   Lcom/wod/dao/User;
    }
    SourceFile: "User.java"
    RuntimeVisibleAnnotations:
      0: #23()
      1: #24(#9=s#25)
    

    类加载过程

    • loading:class文件通过类加载器加载到内存
    • linking:验证class格式-》静态变量赋默认值-》将类、方法、属性等符号引用(常量池的引用)解析为直接引用
    • initialing:类初始化,静态变量赋初始值

    类加载器classloader

    双亲委派机制

    • 判断是否已加载:自定义加载器-》AppClassLoader-》ExtClassLoader-》BootStrapClassLoader(native)
    • 依次尝试加载:BootStrapClassLoader-》ExtClassLoader-》AppClassLoader-》自定义加载器

    体现双亲委派的代码

    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        if (parent != null) {
                            c = parent.loadClass(name, false);
                        } else {
                            c = findBootstrapClassOrNull(name);
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }
    
                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // 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;
            }
    

    热加载

    • tomcat
    • 双亲委派机制表示加载过就不再加载,所以需要自定义classloader重写loadClass打破双亲委派才能重新加载
    public class SuccessedClassReloading2 {
        private static class MyLoader extends ClassLoader {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
    
                File f = new File("D:/work/develop/juc_test/target/classes/" + name.replace(".", "/").concat(".class"));
    
                if(!f.exists()) return super.loadClass(name);
    
                try {
    
                    InputStream is = new FileInputStream(f);
    
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                return super.loadClass(name);
            }
        }
    
        public static void main(String[] args) throws Exception {
            MyLoader m = new MyLoader();
            Class clazz = m.loadClass("com.wod.dao.User");
    
            m = new MyLoader();
            Class clazzNew = m.loadClass("com.wod.dao.User");
    
            //false则表示重新加载成功
            System.out.println(clazz == clazzNew);
        }
    }
    
  • 相关阅读:
    理解jquery的$.extend()、$.fn和$.fn.extend()
    jquery中的$.fn的用法
    【转】区别 (function($){...})(jQuery)、$(function(){ })和$.fn
    linux常用目录和文件解析
    Linux通配符与正则表达式
    CentOS6配置邮件发送
    svn简单上传下载文件命令
    CentOS6源码安装zabbix服务器
    搭建zabbix服务器常见问题解析处理
    CentOS6安装Zabbix(RPM包)
  • 原文地址:https://www.cnblogs.com/wod-Y/p/13220993.html
Copyright © 2011-2022 走看看