登陆 | 注册 设为首页 | 加入收藏 | 联系我们
太和养老网
热词老年艺术  助老机构  养老系统  

中心区域北京 天津 河北 山西 内蒙古 辽宁 吉林 黑龙江 上海 江苏 浙江 安徽 福建 江西 山东 河南 湖北 湖南 广东 广西 海南 重庆 四川 贵州 云南 西藏 陕西 甘肃 青海 宁夏 新疆 香港 澳门 台湾 全国城市养老院目录 全国县市养老院汇总目录 太和AI作品展 太和养老艺术网AI作品展示

Java 类加载器学习-飞

 

2023/7/6 17:11:26 ('互联网')

前言

类加载器属于JVM的一个重要知识点,也是Java安全里命令执行、webshell管理器编写的常用技术。

类加载器简介

我们知道java源文件在运行前会被编译为class类文件,存放着编译后JVM虚拟机指令的二进制字节流。当使用某类时,JVM就会加载它并在内存中创建对应的class对象。该过程称为类的加载。

类加载过程

过程如下:

image.png加载阶段
通过一个类的完全限定名称来查找该类的字节码文件,并利用字节码文件来创建一个Class对象。链接阶段
负责把类的二进制数据合并到JRE中。
又可以分为以下三个阶段:
1、验证阶段
用来确保Class文件中包含的字节流信息符合当前Java虚拟机的要求。
2、准备阶段
为static修饰的静态类变量分配内存,并将其设置为默认值;
不会分配并初始化用 final 修饰符修饰的 static 变量,因为该类变量在编译时就会被分配到内存空间;
不会分配并初始化实例变量,因为实例变量会随对象一起分配到 Java 堆中,而不是 Java 方法区;
3、解析阶段
将类的二进制数据中的符号引用转换为直接引用。初始化阶段
类加载的最后阶段,若该类具有父类,则先对父类进行初始化,执行静态变量赋值和静态代码块代码,成员变量也将被初始化。类加载器

类加载器可以分为两种:
一种是Java虚拟机自带的类加载器,分别为启动类加载器、扩展类加载器、系统类加载器。

启动类加载器(Bootstrap ClassLoader)
    底层由C/C++ 实现,不继承java.lang.ClassLoader类,不存在父类加载器;
public static void main(String[] args) {    ClassLoader c1 = Object.class.getClassLoader();    System.out.println(c1); // 加载器打印出来的结果是null}
    负责加载%JAVA_HOME%/jre/lib目录下的核心类库,比如 rt.jar、charsets.jar 等;负责加载 %JAVA_HOME%/jre/classes 中的类;
扩展类加载器(Extensions ClassLoader)
    加载 Java 的扩展列库,默认加载 %JAVA_HOME%/jre/lib/ext扩展目录中的类库或由 java.ext.dirs系统变量指定的目录下的类库;系统类加载器的父类是扩展类加载器,扩展类加载器的父类是启动类加载器;
系统类加载器(App ClassLoader)
    负责加载ClassPath环境变量下或者系统属性java.class.path的所有类库,主要是加载开发人员编写的类库;Java 程序默认的类加载器;是用户自定义的任何类加载器的默认父类加载器;

一种是用户自定义的类加载器,是java.lang.ClassLoader子类实例。
加载用户自定义路径下的类包,通过继承java.lang.ClassLoader类的方式来实现。即父类为系统类加载器。

双亲委派机制

通过上面学习,我们知道了JVM默认有三种类加载器。除了根类加载器之外,其他的类加载器都需要有自己的父加载器。
那在加载class字节码文件时到底哪个类加载器会去加载呢?这实际上就是"双亲委派机制"。

image.png

当一个类加载器需要加载类时,先去判断该类是否已经被加载,如果已加载则直接返回,如果没有被加载,就向上委托父类加载器。父类加载器也会重复同样的操作,直到"启动类加载器"。确定类未被加载,启动类加载器首先会去对应的目录下%JAVA_HOME%jre/lib/搜索该类。如果找到就加载,如果没有找到就去子类加载器重复同样的操作,去对应的目录下查找该类。最后到用户自定义的类加载器,如果还没有找到就抛出ClassNotFoundException异常退出。

自定义类加载器

下面来看一看java.lang.ClassLoader.class中的几个核心方法。
loadClass(String name, boolean resolve)
也是双亲委托模式的代码实现。
该方法会先调用findLoadedClass(String)来检查类是否已经加载过;
接着递归调用父类加载器,如果父类加载器不为null,则调用父类加载器的的loadClass()方法来寻找该类并加载,如果父类加载器为null,则说明到了引导类加载器;
如果父类加载器均找不到这个类,则调用自定义的findClass()方法寻找并加载该类;
最后根据resolve值选择是否对 Class 进行动态链接操作。

image.png

defineClass(String name, byte[] b, int off, int len)
该方法主要将类的字节流转换为java.lang.Class实例对象。

String name  表示二进制形式的类名byte[] b  表示类的字节流,字节流可以来自Class文件,也可以来自网络或其他途径int off   表示类的字节流的起始偏移量int len   表示类的字节流的大小

findClass(String name)
该方法用来查找一个类,在自定义类加载器时,一般我们需要重写这个方法。以此来获取要加载类的字节码,然后调用defineClass()方法生成Class对象。

所以想自定义实现类加载器,必须满足:
1、继承java.lang.ClassLoader.class
2、重写findClass()方法

过程
下面尝试编写一个Test类

public class Test  {    public String Demo1(){       return "hello cseroad";    }}

将该类进行编译生成class字节码文件。
再编写一个方法获取该class字节码二进制文件的byte数组。

import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.util.Arrays;/** * @author cseroad */public class Demo {    public static byte[] getBytesByFile(String pathStr) {        File file = new File(pathStr);        try {            FileInputStream in = new FileInputStream(file);            ByteArrayOutputStream baos = new ByteArrayOutputStream();            byte[] buf = new byte[1024];            int len = -1;            while ((len = in.read(buf)) != -1) {                baos.write(buf, 0, len);            }            byte[] data = baos.toByteArray(); // 读取到的字节码的二进制数据            in.close();            baos.close();            return data;        } catch (Exception e) {            e.printStackTrace();        }        return null;    }    public static void main(String[] args) {        Demo demo = new Demo();        byte[] bytesByFile = demo.getBytesByFile("/Users/cseroad/IdeaProjects/Project_Java/out/production/Java_study/com/atguigu/test/Test.class");        System.out.



扫码加微信详细咨询太和智慧养老产品和平台服务!

 

 





版权声明:

---------------------------------------------------------------


所有信息来源于互联网,本文的版权归原作者所有,不代表本网观点和立场。

本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请发送邮件至 81480447@qq.com 举报,一经查实,本站将立刻删除。



扫码加微信详细咨询太和智慧养老产品和平台服务!

 

养老资讯
助老机构介绍
评论
已有 0 条评论

最新评论

推荐养老院

您希望养老院位于
  • 不限
  • 东城
  • 西城
  • 崇文
  • 宣武
  • 朝阳
  • 丰台
  • 石景山
  • 海淀
  • 门头沟
  • 房山
  • 通州
  • 顺义
  • 昌平
  • 大兴
  • 怀柔
  • 平谷
  • 延庆
  • 密云
您希望的价格范围
  • 不限
  • 500以下
  • 500-1000
  • 1000-2000
  • 2000-3000
  • 3000-5000
  • 5000以上
老人的情况是
  • 不限
  • 自理
  • 半自理
  • 全护理
  • 特护

姓名

年龄

电话

全国城市养老院



关于我们 | 联系方式 | 网站地图 | 友情链接

Copyright 2010-2022 京ICP备18035644号-3 北京太和 版权所有