精华内容
参与话题
问答
  • 双亲委托机制

    2018-01-31 20:57:45
    当前类applicationclassloader加载类的时候,首先查看这个类是否被加载过,被加载过直接返回,没有加载过会委托父类尝试加载,父类没有加载过会继续委托其父类,一直到bootstrapclassloader。 这样做的好处就是避免...

    当前类applicationclassloader加载类的时候,首先查看这个类是否被加载过,被加载过直接返回,没有加载过会委托父类尝试加载,父类没有加载过会继续委托其父类,一直到bootstrapclassloader。

    这样做的好处就是避免用户自己恶意写了一些与基础类相同名字类所造成的错误。

    从上面可以看出loadClass方法调用了loadcClass(name,false)方法,那么接下来我们再来看看另外一个loadClass方法的实现。

    Class loadClass(String name, boolean resolve)

     

    protected synchronized Class<?> loadClass(String name, boolean resolve) 

     throws ClassNotFoundException   

     {  // First, check if the class has already been loaded  Class c = findLoadedClass(name);

    //检查class是否已经被加载过了  if (c == null)

     {     

     try {      

    if (parent != null) {         

     c = parent.loadClass(name, false); //如果没有被加载,且指定了父类加载器,则委托父加载器加载。    

      } else {        

      c = findBootstrapClass0(name);//如果没有父类加载器,则委托bootstrap加载器加载      } 

         } catch (ClassNotFoundException e) {         

     // If still not found, then invoke findClass in order          

    // to find the class.         

     c = findClass(name);//如果父类加载没有加载到,则通过自己的findClass来加载。      } 

     } 

     if (resolve) 

    {     

     resolveClass(c); 

     }  

    return c;

    }

    类加载的主要步骤

    装载: 把class文件装载到内存中

    链接 检验class文件的准确性,分配静态变量的空间

    初始化:静态变量赋予初始值,静态代码块初始化

    展开全文
  • jvm 类加载机制双亲委托机制

    千次阅读 2016-12-21 11:20:24
    1.ClassLoader分为启动...1.1 jvm中ClassLoader会协同工作,就是说在加载一个class文件时,系统会判断被加载的类是否已经被加载,倘若已经被加载那么就会返回这个可用的类,要是这个类没有被加载,就会请求双亲处理,如

    1.ClassLoader分为启动类加载器(BootStrap ClassLoader)、拓展类加载器(Extension ClassLoader)、应用类加载器(App ClassLoader)
    1.1 jvm中ClassLoader会协同工作,就是说在加载一个class文件时,系统会判断被加载的类是否已经被加载,倘若已经被加载那么就会返回这个可用的类,要是这个类没有被加载,就会请求双亲处理,如果双亲请求失败则会自己加载。我贴出了一段官方源码给大家看看

     /**
         * Loads the class with the specified <a href="#name">binary name</a>.  The
         * default implementation of this method searches for classes in the
         * following order:
         *
         * <ol>
         *
         *   <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
         *   has already been loaded.  </p></li>
         *
         *   <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
         *   on the parent class loader.  If the parent is <tt>null</tt> the class
         *   loader built-in to the virtual machine is used, instead.  </p></li>
         *
         *   <li><p> Invoke the {@link #findClass(String)} method to find the
         *   class.  </p></li>
         *
         * </ol>
         *
         * <p> If the class was found using the above steps, and the
         * <tt>resolve</tt> flag is true, this method will then invoke the {@link
         * #resolveClass(Class)} method on the resulting <tt>Class</tt> object.
         *
         * <p> Subclasses of <tt>ClassLoader</tt> are encouraged to override {@link
         * #findClass(String)}, rather than this method.  </p>
         *
         * <p> Unless overridden, this method synchronizes on the result of
         * {@link #getClassLoadingLock <tt>getClassLoadingLock</tt>} method
         * during the entire class loading process.
         *
         * @param  name
         *         The <a href="#name">binary name</a> of the class
         *
         * @param  resolve
         *         If <tt>true</tt> then resolve the class
         *
         * @return  The resulting <tt>Class</tt> object
         *
         * @throws  ClassNotFoundException
         *          If the class could not be found
         */
        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;
            }
        }

    1.2当系统加载一个类时,会先从从顶层的启动类加载器开始往下加载,一层一层往下找,直到找到相关的类
    现在我来验证一下,首先补充一个知识点
    这里写图片描述
    我们会创建好3个java类
    TestMain.java、HelloLoader.java、HelloLoader.java(大家肯定会很奇怪为什么要创建两个一样的java类,大家注意往下看其实不一样方法体不一样)

    HelloLoader.java
    package testjvm.classsloader;
    
    public class HelloLoader {
        public void print() {
            System.out.println("I am in Boot ClassLoader");
        }
    
    }
    HelloLoader.java
    package testjvm.classsloader;
    
    public class HelloLoader {
        public void print() {
            System.out.println("I am in App ClassLoader");
        }
    
    }
    package testjvm.classsloader;
    
    public class TestMain {
        public static void main(String[] args) {
            HelloLoader helloLoader = new HelloLoader();
            helloLoader.print();
        }
    
    }

    首先我们将方法体是App的java类文件和TestMain 类文件放到同一包下进行编译
    javac testjvm/classsloader/*.java
    将方法体是Boot的java类文件放到E:\testjava\testjvm\classsloader 目录进行编译
    javac testjvm/classsloader/*.java

    然后到TestMain 包文件目录下执行java命令
    这里写图片描述

    这里写图片描述

    1.3.判断一个类是否已经加载是从当前级别类加载器开始判断的,如果这个类已经在当前级别类加载器中,就不会请求上层类的加载器了,如果不在就会向上层层去判断,在判断类是否已经被加载时,顶层类加载器不会询问底层类加载器
    以下方法进行验证
    改写TestMain.java文件

    package testjvm.classsloader;
    
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class TestMain {
        public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException,
                IllegalArgumentException, InvocationTargetException {
            ClassLoader classLoader = TestMain.class.getClassLoader();
            byte[] byteLoader = loadClassBytes("testjvm.classsloader.HelloLoader");
            Method mdClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
            mdClass.setAccessible(true);
            mdClass.invoke(classLoader, byteLoader, 0, byteLoader.length);
            mdClass.setAccessible(false);
    
            HelloLoader helloLoader = new HelloLoader();
            helloLoader.print();
        }
    
        private static byte[] loadClassBytes(String name) {
            FileInputStream in = null;
            try {
                String classFilePath = getClassFile(name);
                System.out.println("类路径" + classFilePath);
                in = new FileInputStream(classFilePath);
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                int ch;
                while ((ch = in.read()) != -1) {
                    byte b = (byte) ch;
                    buffer.write(b);
                }
                in.close();
                return buffer.toByteArray();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        private static String getClassFile(String name) {
            StringBuffer sb = new StringBuffer("E:\\sosino\\workspace\\sosino-shop-630\\testjvm\\src");
            name = name.replace('.', File.separatorChar) + ".class";
            sb.append(File.separator + name);
            return sb.toString();
        }
    
    }

    这里写图片描述

    展开全文
  • JVM 双亲委托机制

    2019-09-24 10:15:18
    存在4种加载器 1.引导类加载器 2.扩展类加载器 3.应用程序类加载器 4.自定义类加载器 从下往上从1开始记载java类,1能加载就不用从2,如果不能加载在找到2.依次类推。 可以使 核心库类型安全。 ......

    存在4种加载器

    1.Bootstrap ClassLoader:启动类加载器,也叫根类加载器,负责加载java的核心类库,例如(%JAVA_HOME%/lib)目录下的rt.jar(包含System,String这样的核心类),根类加载器非常特殊,它不是java.lang.ClassLoader的子类,它是JVM自身内部由C/C++实现的,并不是java实现的

    2.Extension ClassLoader:扩展类加载器,负责加载扩展目录(%JAVA_HOME%/jre/lib/ext)下的jar包,用户可以把自己开发的类打包成jar包放在这个目录下即可扩展核心类以外的功能

    3.System ClassLoader\APP ClassLoader,系统类加载器,又称为应用程序类加载器,是加载CLASSPATH环境变量下所指定的jar包与类路径,一般来说,用户自定义的就是由APP ClassLoader加载的

    4.自定义类加载器。

    从下往上从1开始记载java类,1能加载就不用从2,如果不能加载在找到2.依次类推。

    可以使 核心库类型安全。

    展开全文
  • JVM双亲委托机制

    2019-09-24 13:18:22
    JVM类加载机制中,加载阶段主要由类加载器对类进行加载,然后读取类的二进制字节流。一个类的确定由类的名称和类的加载器唯一标识。但如果同一个类,一个由自定义加载器加载,一个由启动类加载器加载。则两个类在...

    JVM类加载机制中,加载阶段主要由类加载器对类进行加载,然后读取类的二进制字节流。一个类的确定由类的名称和类的加载器唯一标识。但如果同一个类,一个由自定义加载器加载,一个由启动类加载器加载。则两个类在判定时会提示不是同一个对象。这是由于不同的类加载器所造成的。

     

    对于JVM中,主要有以下加载器。启动类加载器,扩展类加载器,应用程序类加载器,自定义加载器。

     

    假如我们对一个类的加载,将其加载交给父类加载器,父类加载器再往上递增,如果父类加载器可以完成此任务,就成功返回,如果不行,再由自己加载。这样就可以避免不同的类加载器导致的同一个类不同加载器所导致的不一致问题。这就是双亲委托模式。

    转载于:https://www.cnblogs.com/CloudStrife/p/7200064.html

    展开全文
  • java 双亲委托机制

    2020-11-10 16:29:33
    JVM设计者把类加载阶段中的“通过’类全名’来获取定义此类的二进制字节流”这个动作放到Java...2.双亲委派模型 从虚拟机的角度来说,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),该
  • java ClassLoader类解析-双亲委托机制

    万次阅读 2015-10-27 14:43:05
    做Java开发,对于ClassLoader的机制是必须要熟悉的基础...本文将会从JDK默认的提供的ClassLoader,双亲委托模型,如何自定义ClassLoader以及Java中打破双亲委托机制的场景四个方面入手去讨论和总结一下。 JDK默认Cla
  • 类加载:双亲委托机制/双亲委派机制 类加载:当程序中需要使用到的某个类的时候,必须先将这个类对应的.class文件加载到内存中。 ClassLoader类加载器负责到指定的路径中查询.class文件,并且加到内存中,将其生成一...
  • jvm如何打破双亲委托机制

    万次阅读 2020-07-09 20:03:51
    打破双亲委托机制 重写父类ClassLoader的loadClass方法 package com.morris.jvm.classloader; public class BreakDelegateClassLoader extends MyClassLoader { @Override protected Class<?> loadClass...
  • 深入理解双亲委托机制

    千次阅读 2018-07-31 16:59:47
    JVM设计者把类加载阶段中的“通过'类全名'来获取定义此类的二进制字节流”这个动作放到Java虚拟机外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块称为“类加载器”...2.双亲委派模...
  • Java之双亲委托机制

    千次阅读 2019-05-22 00:16:04
    双亲委派机制的工作流程: 1. 当前ClassLoader首先从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。 每个类加载器都有自己的加载缓存,当一个类被加载了以后就会放入缓存,等...
  • 一、类的加载 概述 1:当程序要使用某个类时,类未被加载到内存中,系统会通过三步实现类的初始化(加载-连接-初始化) 2:得到类加载器:Class#getClassLoader() 3:类加载器(class loader)用来加载 Java 类...
  • Classloader的双亲委托机制

    千次阅读 2016-11-16 23:12:03
    JVM自带的ClassLoader类 JDK中提供了三个ClassLoader,根据层级从高到低为: Bootstrap ClassLoader,主要加载JVM自身工作需要的类。 Extension ClassLoader,主要加载%JAVA_HOME%\lib\ext目录下的库类。...
  • ART双亲委托机制杂记

    2020-02-24 11:46:55
    1.ART双亲委托机制: PathClassLoader,DexClassLoader --继承自--> BaseDexClassLoader --继承自--> ClasssLoader protected Class<?> loadClass(String name, boolean resolve) throws Clas...

空空如也

1 2 3 4 5 ... 20
收藏数 880
精华内容 352
关键字:

双亲委托