【JVM专题】类加载相关

本问题对应的项目链接:高频题回答模版训练

PS:这块相对考的不多

1、JAVA类加载过程介绍一下?

2、双亲委派原则了解吗?介绍一下

3、为什么需要双亲委派?

4、怎么打破双亲委派模型?了解过吗?

5、类加载器有哪些?介绍几个常见的类加载器

共以下 4 个回答

  • LilyBoy 永久会员 2023年9月17日 上午10:02

    1、JAVA类加载过程介绍一下?
    加载- 通过全类名获取定义此类的二进制字节流
    验证是连接阶段的第一步,这一阶段的目的是确保 Class 文件的字节流中包含的信息符合《Java 虚拟机规范》的全部约束要求,保证这些信息被当作代码运行后不会危害虚拟机自身的安全。
    准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中分配。
    解析阶段是虚拟机将常量池内的符号引用替换为直接引用的过程。
    初始化阶段是执行初始化方法 ()方法的过程,是类加载的最后一步,这一步 JVM 才开始真正执行类中定义的 Java 程序代码(字节码)。

    2、双亲委派原则了解吗?介绍一下
    JVM的类加载器是有亲子层级结构的,就是说启动类加载器是最上层的,扩展类加载器在第二层,第三层是应用程序类加载器,最后一层是自定义类加载器。
    1、启动类加载器
    Bootstrap ClassLoader,他主要是负责加载我们在机器上安装的Java目录下的核心类的。
    2、扩展类加载器
    Extension ClassLoader,这个类加载器其实也是类似的,就是你的Java安装目录下,有一个“lib\ext”目录。这里面有一些类,就是需要使用这个类加载器来加载的,支撑你的系统的运行。
    3、应用程序类加载器
    Application ClassLoader,这类加载器就负责去加载“ClassPath”环境变量所指定的路径中的类。其实你大致就理解为去加载你写好的Java代码吧,这个类加载器就负责加载你写好的那些类到内存里。
    4、自定义类加载器
    除了这三种类加载器之外,用户还可以加入自定义的类加载器来进行拓展,以满足自己的特殊需求。就比如说,我们可以对 Java 类的字节码( .class 文件)进行加密,加载时再利用自定义的类加载器对其解密。

    • 在类加载时,系统首先会判断当前类是否被加载过。已加载的类会直接返回。否则才会尝试加载(每个父类加载器都会走一遍这个流程)
    • 类加载器在进行类加载时,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成(调用父类加载器loadClass()方法来加载类)。这样的话,所有的请求最终都会传送到顶层的启动类加载器中;
    • 只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载(调用自己的findClass()方法来加载类)

    **3、为什么需要双亲委派?

    保证唯一性;
    核心库的安全性和稳定性;

    **4、怎么打破双亲委派模型?了解过吗?
    打破双亲委派模型的思路就是在加载类时,不按照依次往上匹配类加载器的方式加载。那么只需要自定义一个 ClassLoader,然后重写 loadClass 方法,自己定义一个其他的加载方式就行。

    5、类加载器有哪些?介绍几个常见的类加载器
    已完成2

    0 赞同 0 条回复
  • 中国用户 永久会员 2023年9月11日 下午8:58

    1.第一步是通过Classloder加载字节码文件到内存,第二步是链接,检验加载的class的正确性和安全性,然后为类变量分配存储空间并设置初始值,然后jvm将常量池内的符号引用转换为直接引用,第三部是初始化,执行类变量赋值和静态代码块。
    2.双亲委派机制自底向上为自定义的classloader,appclassloader,extclassloader,bootstrapclassloader来检验类是否已经加载
    3.避免重复加载类。
    4.自定义classloader然后重新loadclass()方法

    0 赞同 0 条回复
  • 小肸 永久会员 2023年8月20日 下午8:24

    第一步是加载,类加载器查找并以二进制数据格式加载类文件到内存。第二步是连接,首先做验证工作,验证类文件的格式对不对,是不是.class文件格式,然后验证类的结构定义对不对,然后做准备工作,为类中的字段分配空间。最后做解析工作,将符号引用转换成直接引用。第三步是初始化,执行\<clinit>方法,执行类变量的赋值语句和类的静态代码块。类经过初始化后就可以被程序使用。

    当类加载器去加载一个类时,会交给它的父级类加载器加载,如果父级类加载器的类路径中包含这个类,这个类优先被父级类加载器加载。这样可以避免开发者自己写的类覆盖了Java的核心基础类。比如开发者自己写了一个String类,当应用程序类加载器去加载String类会让扩展类加载器优先加载String类,扩展类加载器就会优先让启动类加载器优先加载String类,最后由启动类加载Java的核心基础类String类,而不是由应用程序加载开发者自己写的String类。保证了Java的核心基础类不会被覆盖,同时也避免了多个类加载器加载同一个类造成混乱。

    如果想要打破双亲委派模型,可以自己定义一个类加载器ClassLoad,然后重写它的loadclass()方法。

    0 赞同 0 条回复
  • 秊 永久会员 2023年8月17日 下午4:29

    1、JAVA类加载过程介绍一下?

    Java 类加载分为三个阶段,第一个阶段是 “加载”,是类加载过程的起始点,在这个阶段,虚拟机通过类的全限定名找到对应的二进制字节码。这个过程主要是由类加载器来完成的;第二个阶段是 “连接“,它又包括三个子阶段:验证,准备和解析。验证阶段,虚拟机主要会验证加载的字节码是否符合 JVM 规范,包括类的结构,语义等方面。准备阶段,虚拟机会为类的静态字段分配内存并设置默认值。解析阶段,虚拟机会将符号引用转换为直接引用,这样虚拟机可以直接定位到目标类,方法等等;第三个阶段是 ”初始化“,这个阶段虚拟机主要会执行类的初始化代码,之后就完成了类加载过程。

    2、双亲委派原则了解吗?介绍一下

    双亲委派模型是一种层次化的类加载结构,从上往下依次由 BootStrapClassLoader,ExtClassLoader,AppClassLoader 和 自定义的 ClassLoader 构成。其中 BootStrapClassLoader,由 C++ 编写,用来加载核心库 Java.*;ExtClassLoader 用来加载扩展库 javax.*;AppClassLoader 用来加载用户类路径上的所有库;最后自定义的 ClassLoader 用来实现定制化加载。

    它的工作原理为:当一个类加载器接收到类加载的请求时,它首先将这个请求委托给它的父加载器进行处理,直到顶层的 BootStrapClassLoader 被委托为止。如果父加载器可以找到并加载这个类,那么这个类加载的请求就结束了,否则,子加载器才会尝试加载该类,以此类推。

    3、为什么需要双亲委派?

    这种委派机制可以确保 Java 类的唯一性,避免类的重复加载。同时还保证了 Java 核心库的安全性和稳定性。因为Java核心库都是由 BootStrapClassLoader 加载的,任何用户自定义的类都无法覆盖核心类库中的类。

    4、怎么打破双亲委派模型?了解过吗?

    打破双亲委派模型的思路就是在加载类时,不按照依次往上匹配类加载器的方式加载。那么只需要自定义一个 ClassLoader,然后重写 loadClass 方法,自己定义一个其他的加载方式就行。

    实际的应用中,Tomcat 就破坏了双亲委派模型。通常在用 Tomcat 部署 web 应用时,需要将 war 包放在 webapp 目录下,然后 Tomcat 就能运行这个 web 应用了。现在假设有两个 web 应用类,并且它们刚好都有一个全限定名都相同的 user 类,但具体的实现不一样。如果按照双亲委派模型的思路,最终只有一个 user 能被加载,也就只有一个 web 应用能部署成功。Tomcat 为了解决这个问题,它给每个 Web 应用都创建了一个 WebAppClassLoader,该类加载器重写了 loadClass 方法,优先加载当前应用目录下的类,如果当前目录找不到,才会一层一层往上找。这样的话,Tomcat 就做到了 Web 应用层级别的隔离。

    还有比如 JDBC 也算是破坏了双亲委派模型,当我们使用 JDBC 时,是用 DriverManager.getConnection( ) 来获取连接的,但由于 DriverManager 本身是属于 Java 包下的,是由 BootStrapClassLoader 加载的,而通过 getConnection 得到的是其它厂商的实现类,显然是不能由 BootStrapClassLoader 加载。那么在这里就用到了 “线程上下文加载器”,DriverManager 在初始化时就会去得到线程上下文加载器,然后由它代替 BootStrapClassLoader 来加载具体的 Connection 类。

    5、类加载器有哪些?介绍几个常见的类加载器

    见 2 、

    1 赞同 0 条回复

# 回答此问题

后才能回答