精华内容
下载资源
问答
  • 类加载顺序 上图所示的是类加载的顺序,按照大的顺序可以分为加载、链接、初始化 其中链接又可以分成验证、准备、解析三个步骤 加载 1.将类的class文件读入到内存中 加载类文件的方式有: 1. 本机文件加载 2.jar包...

    类加载顺序

    在这里插入图片描述

    上图所示的是类加载的顺序,按照大的顺序可以分为加载、链接、初始化
    其中链接又可以分成验证、准备、解析三个步骤

    加载

    1.将类的class文件读入到内存中

    加载类文件的方式有: 1. 本机文件加载 2.jar包加载 3.网络加载 4.源文件动态编译加载

    2.创建一个java.lang.class文件

    连接

    1.验证:类结构是否正确,是否与其他类协调一致

    2.准备:为类分配内存,并设置默认初始值

    3.解析:将二进制文件的符号引用替换成直接引用

    初始化

    对类的变量进行初始化
    使用静态代码块初始化、申明类变量初始值

    • 子类和父类的关系
      父类的静态变量
      父类的静态代码块
      子类的静态变量
      子类的静态代码块
      父类非静态变量
      父类非静态代码块
      父类构造方法
      子类非静态变量
      子类非静态代码块
      子类构造方法

    双亲委派模式

    在这里插入图片描述
    java 里有3中默认的类加载器

    加载器种类 解释
    启动类加载器 从JAVA_HOME/lib 路径下找
    扩展类架子器 从JAVA_HOME/lib/ext 路径下找
    应用程序类加载器 从classpath 路径下找
    自定义加载器 我们程序员自己定义的加载器

    new 一个类的时候 ,首先jvm会去看下当前类加载器有没有父类的加载器,有就把这个加载请求交给父类,一直如此,直到到达最顶层的启动类加载器,然后,在一级一级的往下看能不能加载,能加载就加载,不能就把这个加载任务交给子类

    举一个例子,当我new Dog() 的时候

    1. 首先这个请求会交给应用程序类加载器,然后会被交给扩展类加载器
    2. 扩展类加载器会将这个请求交给启动类加载器
    3. 启动类加载器开始尝试去JAVA_HOME/lib里找,没有,交还给扩展类加载器
    4. 扩展类加载器从JAVA_HOME/lib/ext 里找,没有交还给应用程序类加载器
    5. 应用程序类从classpath 里去找,没有交给自定义加载器
    6. 要是自定义加载器还没有就抛出异常
      上述的过程只要有一个加载器加载到了就不再下放了。
    • 双亲委派机制的优势
      可以避免java的核心api 被篡改,比如你自定义了一个String 类,这个类是无效的,他绝对不会被加载,这样有效避免了类加载导致的安全问题

    自定义类加载器

    接下去我们实现一个自定义的类加载器,利用这个加载器来加载一个类

    • 首先简单的构建一个类

      package com.example.demo;
      
      public class Dog {
          public String name;
      }
      

      这是一个很简单的类,我们把它编译成class 文件放在d:盘的根目录下

    • 构建我们自己的类加载器

      public class MyLoader extends ClassLoader {
          @Override
          protected Class<?> findClass(String name) throws ClassNotFoundException {
              File file = new File("D:/Dog.class");
              try {
                  FileInputStream fileInputStream = new FileInputStream(file);
                  ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                  //每次读取的大小是4kb
                  byte[] b = new byte[4 * 1024];
                  int n = 0;
                  while ((n = fileInputStream.read(b)) != -1) {
                      outputStream.write(b, 0, n);
                  }
                  //将Dog.class类读取到byte数组里
                  byte[] classByteArray = outputStream.toByteArray();
                  //调用defineClass 将byte 加载成class
                  Class<?> aClass = this.defineClass(name, classByteArray, 0, classByteArray.length);
                  return aClass;
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return super.findClass(name);
          }
      }
      

      上面的代码中,我们自定义了一个类让他去继承ClassLoader,然后重写其中的findClass方法,我们重写后的逻辑就是自己的指定的目录,也就是d盘下找到Dog.class文件 然后读取到一个byte数组中,然后调用defineClass 加载这个类。

    • 下面用一个简单的程序测试下

      public class UserDemo {
          public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
              MyLoader myLoader = new MyLoader();
              Class<?> aClass = Class.forName("com.example.demo.Dog", true, myLoader);
              Object o = aClass.newInstance();
              System.out.println(o);
              System.out.println(o.getClass().getClassLoader());
          }
      }
      

      这里的Class.forname 和以前不一样,我们后面对了两个参数,true代表类重新加载,myLoader就是我们自定义的类加载器

      运行后显示:

      com.example.demo.Dog@2e817b38
      com.example.demo.MyLoader@4d405ef7
      

      可以看到已经使用了我们自定义的类加载器。

    • 这里有一点要注意,就是个别编译器比较智能,如我使用的idea,他们会自定编译,直接把你的java文件编译成class 放入classpath下去了,所以在运行请务必吧这个文件删除,如果你用的是idea 把整个target删除就行

    展开全文
  • java自定义类加载

    2018-09-09 15:10:31
    加载的过程 是从上到下的顺序。跟windows的消息钩子的执行方向相反。 之前CC++写过pe文件加载 非常麻烦,按照pe格式分配内存加载到程序空间 java提供了自定义加载器的机制 还是比较方便的, 总体流程:继承...

    java的加载器分为三类

    引导加载器 C编写

    扩展加载器

    应用程序加载器

    加载的过程 是从上到下的顺序。跟windows的消息钩子的执行方向相反。
    之前CC++写过pe文件加载 非常麻烦,按照pe格式分配内存加载到程序空间

    java提供了自定义加载器的机制 还是比较方便的,
    总体流程:继承ClassLoader—-看看有没有加载过该类—-没有加载过看看父类能不能加载—-父类不能加载,自己去加载—-自己加载的流程—-获得类文件的byte[]—-调用父类接口defineClass得到Class对象

    贴代码

    自定义从文件加载类

    package top.demo.load;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    
    public class FileLoad extends ClassLoader{
    
        public String rootPath;
        //F:
    
        public FileLoad(String rootPath) {
            super();
            this.rootPath=rootPath;
    
        }
    
    
        //className top.demo.load.Test
        public Class<?> loadFileClass(String className) throws Exception {
            Class<?>cl=null;
            try {
                cl=findClass(className);
            } catch (ClassNotFoundException e) {
                //e.printStackTrace();
                System.out.println("没有加载过该类");
            }
    
            if(cl!=null)            
                return cl;
    
            //如果该类没有被加载 交由父类加载
            try {
                cl=super.loadClass(className);
            } catch (ClassNotFoundException e) {
                //e.printStackTrace();
                System.out.println("父类不能加载该类");
            }
    
            if(cl!=null)
                return cl;
    
            //如果父类不能加载,那么我们自己加载
            StringBuilder realPath=new StringBuilder();
            realPath.append(rootPath);
            realPath.append("/");
            realPath.append(className.replace(".", "/"));
            realPath.append(".class");
    
            File file=new File(realPath.toString());
            if(!file.exists()) {
                throw new Exception("没有这个类文件存在");
            }
    
            byte[] classInfo=null;
    
            classInfo=getClassFileInfo(file);
            if(classInfo==null) {
                throw new Exception("读取类文件可能出错");
            }
    
            cl=defineClass(className,classInfo, 0, classInfo.length);
    
            if(cl==null)
                throw new Exception("自定义加载器出错");
    
    
            return cl;
        }
    
        private byte[] getClassFileInfo(File file) {
    
            byte[] classInfo=new byte[(int) file.length()];
            FileInputStream fileIn=null;
    
            try {
                int len=0;
                fileIn=new FileInputStream(file);
    
                try {
                    while(-1!=(len=fileIn.read(classInfo))) {
    
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    classInfo=null;
                    try {
                        fileIn.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                classInfo=null;
            }finally {
                try {
                    fileIn.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
    
    
            return classInfo;
        }
    
    
    }
    

    定义需要加载的类 并且编译成class文件放在 F:\top\demo\load下类名为Test

    定义测试加载类

    package top.demo.load;
    
    public class TestLoad {
    
        public static void main(String argv[])
        {
    
            FileLoad load=new FileLoad("F:");
            Class<?> cl=null;
            try {
                cl=load.loadFileClass("top.demo.load.Test");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(cl!=null ? "成功加载":"加载失败");
    
    
    
        }
    
    
    }
    

    输出结果

    没有加载过该类
    父类不能加载该类
    成功加载

    展开全文
  • 自定义类加载

    2011-09-30 11:05:11
    类加载器public abstract class ClassLoader 解说:它是抽象类,不能直接用。...loadclass类加载顺序 protected synchronized Class&lt;?&gt; loadClass(String name, boolean resolve) throws Class...

    类加载器public abstract class ClassLoader 解说:它是抽象类,不能直接用。可使用其子类如urlclassloader。

    其有两个重要方法:

    loadclass类加载顺序

        protected synchronized Class<?> loadClass(String name, boolean resolve)
    	throws ClassNotFoundException
        {
    	// First, check if the class has already been loaded
    	Class c = findLoadedClass(name);
    	if (c == null) {
    	    try {
    		if (parent != null) {
    		    c = parent.loadClass(name, false);
    		} else {
    		    c = findBootstrapClass0(name);
    		}
    	    } catch (ClassNotFoundException e) {
    	        // If still not found, then invoke findClass in order
    	        // to find the class.
    	        c = findClass(name);
    	    }
    	}
    	if (resolve) {
    	    resolveClass(c);
    	}
    	return c;
        }

     findClass需要子类实现:用于加载具体的类,如类路径等

        protected Class<?> findClass(String name) throws ClassNotFoundException {
    	throw new ClassNotFoundException(name);
        }

     

     

    一、 URLClassLoader cl1=new URLClassLoader(urls, null); 说明?自定义ClassLoader可以使用现成的URLClassLoader指定parent为null,

    new URLClassLoader(urls, null) =》

    URLClassLoader的super(parent);=》

    SecureClassLoader的super(parent);=》

    ClassLoader的this.parent = parent;

    所以最后会将ClassLoader的parent为null。

    所以加载器还是会先从bootStrap中加载类。但不会从ext、app中加载。见以上第9

    另外即使不赋为null,那parent->parent->....最后一定会有一个为null,即还是会执行到9行

    这样好处是:自己写的类加载器不会将JRE的核心类覆盖掉。

     

    二、 自定义ClassLoader可以使用现成的URLClassLoader且可以指定parent为null,为什么有时还要自己写呢?

    虽然可以复用URLClassLoader,但其还是使用classloader的loadClass方法,即流程没变,如果要改变类加载顺序必须重写。

    场景一:

    应用的ClassLoader里面加载了1,2,3,4,5个JAR包。

    自己的ClassLoader想共享应用的1,2,3,4的JAR包,但不想用5的JAR,这时要自己要在里面排除5,可根据包名。

    场景二:

    1.当系统要集成两个开源框架,而这两个框架使用了POI的两个版本的包、2.或者将新框架集成到现有系统时,有包版本冲突

    这时可写自己的类加载器,分别加载不同的版本包 

    展开全文
  • JAVA自定义类加载

    2014-05-30 09:55:54
    import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException;...import java.io.IOException;... * 一、ClassLoader加载类顺序  *
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.ObjectInputStream.GetField;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;

    /**
     *
     * 一、ClassLoader加载类的顺序
     *  1.调用 findLoadedClass(String) 来检查是否已经加载类。
     *  2.在父类加载器上调用 loadClass 方法。如果父类加载器为 null,则使用虚拟机的内置类加载器。
     *  3.调用 findClass(String) 方法查找类。
     * 二、实现自己的类加载器
     *     1.获取类的class文件的字节数组
     *     2.将字节数组转换为Class类的实例
     *
     *
     * @author lei 2011-9-1
     */
    public class Test {

        public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
            //新建一个类加载器
            System.out.println(ClassLoader.getSystemClassLoader());
            MyClassLoader cl = new MyClassLoader("myClassLoader");
            //加载类,得到Class对象
            Class<?> clazz = cl.loadClass("Animal");
            //得到类的实例
            Object animal= clazz.newInstance();
            System.out.println(clazz.getClassLoader());
            Method m = clazz.getMethod("say", null);
            m.invoke(animal, null);
        }

    }

    class MyClassLoader extends ClassLoader {
        //类加载器的名称
        private String name;
        //类存放的路径
        private String path = "F:\\Myeclipseworkspace\\TestClassLoader\\src\\";  //别放bin中

        MyClassLoader(String name) {
            this.name = name;
        }
        
        MyClassLoader(ClassLoader parent, String name) {
            super(parent);
            this.name = name;
        }
        /**
         * 重写findClass方法
         */
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte[] data = loadClassData(name);
            return this.defineClass(name, data, 0, data.length);
        }
        
        public byte[] loadClassData(String filename) {
            filename = filename.replace(".", "//");
            File file = new File(path + filename + ".class");
            int length = (int) file.length();
            byte[] contents = new byte[length];
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                int r = fis.read(contents);
                if (r != length) {
                    throw new IOException("IOException:无法读取" + filename);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fis != null) {
                        fis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return contents;  
        }



    }

    这个class文件不要放上面的Test类的bin中,不然会被Test的类加载器先加载

    public class Animal{
        public void say(){
            System.out.println("hello world!");
        }
    }


    输出:

    sun.misc.Launcher$AppClassLoader@6b97fd
    MyClassLoader@19189e1
    hello world!

    MyClassLoader@19189e1的父加载器是sun.misc.Launcher$AppClassLoader@6b97fd

    展开全文
  • 类加载原理及自定义类加载

    千次阅读 2006-01-18 21:40:00
    《揭示java类加载内幕》一 初识类加载器 java虚拟机通过‘类加载器’来加载类到内存中,即class文件。类加载器相关的类是ClassLoader,这是一个抽象类。java程序的每个类都有一个指向ClassLoader的引用,可以通过...
  • 手把手教你写自定义类加载

    千次阅读 2017-04-16 15:44:50
    虚拟机类加载过程基础可以参考:JVM类加载机制基础 我们知道jvm的类加载是利用...JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述: • 根类加载器(Bootstrap) •
  • JVM中除了根加载器之外其他加载器都是ClassLoader的子类实例, 可以通过扩展ClassLoader的子类,通过重写方法来实现自定义类加载器。 ClassLoader中有两个关键的方法如下, loadClass(...), 系统调用这个方法...
  • 类加载顺序

    2021-03-24 23:35:44
    类加载器: Boottstrap classLoader 引导类...类加载顺序: HelloWord.class 第一次加载时,先由AppClassLoader判断是否有加载该类,没有则向上委托,由ExtClassLoader判断是否加载过该类,没有则继续向上委托,由
  • package classloader; import java.io.ByteArrayOutputStream; import java.io.File;... * 一、ClassLoader加载类顺序 * 1.调用 findLoadedClass(String) 来检查是否已经加载类。 * 2.在父类加
  • Java类加载顺序

    2019-08-27 17:41:42
    Java类加载顺序一.什么是类加载?二.类加载都需要加载哪些内容三.类加载顺序3.1无无扩展类型的加载顺序3.2有扩展类型的加载顺序4 最终得出结论5.注意事项功能快捷键合理的创建标题,有助于目录的生成如何改变文本的...
  • import torch import torch.nn as nn from torch import nn from torchvision import models, datasets, transforms import torch as tc from torch.autograd import Variable from torch.utils.data import ...
  • 这里写自定义目录标题Java内部以及加载顺序1.加载顺序1.静态代码块:使用static关键字和{}声明的代码块(不能存在于方法中,是所属于的)2.构造代码块:和静态代码块的区别是少了static关键字3.普通代码...
  • 在学习Springboot的时候遇到@Configuration的指定顺序加载问题。做个记录,防止以后遇到的时候再次懵逼。 Springboot的执行,有main方法的那个,正常情况下有@SpringBootApplication和@ComponentScan两个注解。...
  • 答:ClassLoader分为4种:Jvm类加载器(BootstarpClassLoader),Jvm扩展类加载器(extClassLoader),系统类加载器(SystemClassLoader),自定义类加载器(AppClassLoader) -------------------------------...
  • 自动加载自定义类

    2011-09-18 01:08:51
    zend中, 自定义类名以 ‘_’ 分隔 ,表示文件的上下级顺序 ,自动加载生效后 , zend会根据你的类名 , 自动寻找到你自定义 。 而不需要手动的require 或 include .  默认的 zend/libriary下的系统是能够...
  • 类加载器的顺序是在所有的系统类加载器的最后,系统类中的类加载器都是根据CLASSPATH路径进行加载的,而如果有自定以的加载器,就可以由开发者任意指派类的加载位置。 编写一个类,放在磁盘中。 package test; ...
  • 继承ClassLoader并且重写findClass方法就可以自定义一个类加载器,具体什么是类加载器以及类加载器的加载过程与顺序下次再说,下面给出一个小demo首先定义一个类,比如MyTest,并且将其编译成class文件,然后放到一...
  • 发现自定义类库的加载方式 是有顺序的。分别是按映射方式 psr4 psr0,其中最高效的,顺序最前的当然是映射方式。我贴出源码,大家看下。private static function findFile($class) { //echo '&lt;pre&gt;';...
  • Java类的加载 Java类的加载是由类加载器来完成的。 一般来说,类加载器分成两类:启动类加载器(bootstrap)和用户自定义的类加载器...在用户自定义类加载器的部分,一般JVM都会提供一些基本实现。应用程序的开发人员也
  • 自定义加载

    2015-05-04 15:48:59
    import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream;... 一、ClassLoader加载类顺序  *  1.调用 findLoadedClass(String) 来检查是否已经加
  • 查看源码,查看打印应用程序banner的顺序。 SpringApplication:可用于从Java main *方法引导和启动Spring应用程序的。( Class that can be used to bootstrap and launch a Spring application fro.
  • 类加载

    2021-03-19 12:02:59
    类加载类加载器自定义加载器类加载器路径类加载顺序查看字节码idea插件 类加载器 源码: 根加载器&&扩展类加载器&&系统加载器&&自定义加载器 自定义加载器 public class CousmerClassLoad ...
  • 清楚了类加载器的功能之后就可以根据自身的需要来实现自定义类加载器,但是需要千万要记住一点,自定义类加载器其加载的顺序是所有系统类加载器的最后。系统类中的类加载器都是根据CLASSPATH路径进行类加载的,...
  • 类加载和初始化 class cycle 首先一个class文件在硬盘里面 然后JVM去对它进行以下行为: Loading,把class文件load到内存,双亲委派(安全) Linking verification,class格式校验 preparation,准备,这时候静态变量赋...
  • JAVA JVM类加载

    2019-07-22 18:15:03
    类加载器 启动类加载器 bootstrap ...自定义类加载器,加载自定义路径 类加载时检查是否存在顺序 自定义类加载器 应用类加载器 扩展类加载器 启动类加载器 类加载到内存时顺序 启动类加载器 扩展类加载器...

空空如也

空空如也

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

自定义类加载顺序