JVM-类的加载面试题

1.1 Java运行时一个类是什么事时候被加载的?

一个类在什么时候被加载虚拟机并没有强制约束,对于HotSpot虚拟机,是按需加载,当真正要用到的时候才开始加载此类;

1.2 一个类的加载过程

1、加载:

        将类的class二进制字节流读进来,在内存中生成一个代表这个类的java.lang.Class对象放入元空间,此阶段程序员可以干预,可以自定义类的加载器来实现类的加载;

2、链接

        验证:验证Class文件的字符流中包含的信息是否符合java虚拟机规范中全部约束条件;(这样能保证虚拟机的安全);cafe babe

        准备: 对类变量赋默认初始值(实例变量要等到new对象的时候才开始初始化),int为0,long为0L,boolean为false,引用类型为null;常量直接进行赋正式值;

        解析:把符号引用翻译为直接引用;

3、初始化:new一个对象,访问一个类的静态属性,修改一个类的静态属性,调用一个类的静态方法,用反射API对一个类进行调用,初始化当前类,其父类也会被初始化......

具体的初始化细节后面叙述

4、使用:使用这个类;

5、卸载:当满足以下几点的时候该类被卸载:大部分情况很难满足

        1、该类的所有实例都被GC,也就是JVM中不存在该Class的任何实例;实例没了

        2、加载该类的ClassLoader已经被GC;加载器没了

        3、该类的java.lang.Class对象没有在任何地方被引用,比如:不能再任何地方通过反射访问该类的方法;Class没了

1.3 一个类被初始化的过程

静态变量:准备阶段赋值为null/0,初始化阶段赋值为初始值

实例变量:创建对象的时候赋值;

静态初始化块:初始化阶段执行;

1.4 继承时父子类的初始化顺序是怎样的?

1、父类静态变量和静态代码块(先声明的先执行);

2、子类静态变量和静态代码块(先声明的先执行);

3、父类的变量和代码块(先声明的先执行);

4、父类的构造函数;

5、子类的变量和代码块(先声明的先执行);

6、子类的构造函数。

1.5 什么是类加载器

在加载阶段:

类加载器是一段代码,通过此代码将类以二进制字节流的形式读取到JVM中;

类加载器通过一个类的全限定名来获取描述该类的二进制字节流;

1.6 JVM有哪些类加载器

一、从JVM虚拟机角度

1、启动类加载器:C++语言实现;

2、其他所有的类加载器:java语言实现,继承于抽象类java.lang.ClassLoader;

二、从开发者角度

 BootstrapClassLoader:启动类加载器

ExtClassLoader:扩展类加载器

AppClassLoader:应用类加载器(系统类加载器)

1.7 JVM中不同的类加载器加载哪些文件?

1、启动类加载器:

<JAVA_HOME>\jre\lib\rt.jar,resources.jar\charsets.jar

2、扩展类加载器

<JAVA_HOME>\jre\lib\ext

被java.ext.dirs系统变量所指定的路径中所有的类库

3、应用类加载器

加载用户类路径上所有的类库:自己写的类、引入的第三方jar包;

1.8 JVM三层类加载器之间的关系是继承吗?

不是;AppClassLoader/ExtClassLoader都是Launcher里面的内部类;他们两个都是继承ClassLoader;

1.9 你了解双亲委派模型吗?

       首先通过系统类加载器加载,然后系统类加载器不加载,委派给扩展类加载器加载,同样,扩展类加载器也不加载,委派给启动类加载器加载;然后开始自顶向下去尝试加载,如果没有找到就交给下面的去尝试加载,直到最后加载成功;        

  1.10 为什么要设计双亲委派模型,有什么好处?

1、确保安全,避免Java核心库被修改;

2、避免重复加载;

3、保证类的唯一性;

1.11 可以打破双亲委派模型吗?如何打破JVM双亲委派模型;

           想要打破这种模型,就自定义一个类的加载器,继承Classloder类,重写其中的loadClass(这个方法是实现双亲委派机制的)方法,使其不进行双亲委派即可;

1.12 如何自定义自己的类加载器

1、继承ClassLoader;

2、覆盖findClass(String name)方法、或者 loadClass方法;

 覆盖findClass(String name)方法 不会打破双亲委派;

loadClass()方法:会打破双亲委派机制;

1.13 ClassLoader 中 的loadClass()、findClass()、defineClass()区别?

loadClass()就是主要进行类加载的方法,默认的双亲委派机制就是在在这个方法中;

findClass()根据名称或位置加载.class字节码;

definclass():这个方法底层是用C++写的,把字节码流转化为java.lang.Class;

1、当我们想要自定义一个类加载器的时候,并且向破环双亲委派模型时,就会重写LoadClass方法;

2、如果我们不想破环双亲委派模型就重写findClass方法即可;在findClass方法中实现自己加载的逻辑就可以了;

1.14 加载一个类采用Class.forName()和ClassLoader有什么区别

1、用Class.forName加载的时候类的信息会被初始化;加载、链接、初始化;

2、如果使用ClassLoader加载类的时候不会初始化,只会进行加载、链接;只有在加载之后使用newInstance之后才会进行初始化;

1.15 你了解 TomCat的类的加载机制吗?

灰色部分为java中的类加载器结构,白色部分为TomCat中的类加载器结构; 

commonClassLoader、CatalinaClassLoader、ShareClassLoader是三个基础类加载器,

 是通过conf/catalina.properties进行配置的;

webApp加载TomCat中webApps中的文件;重写了findclass和loadclass方法,打破了双亲委派机制;(可以有多个webApp加载器,多个项目就有多个)

jsp类加载器用来加载jsp文件;jsp在运行的时候会转换为java,通过jsp转换为class文件;重写了loadclass方法,也打破了双亲委派模型的机制;(可以有多个jsperLoader加载器,多个jsp页面就有多个jsperLoader加载器);

打破了双亲委派的机制,也就是说如果收到类加载的请求首先会尝试自己去加载,如果自己找不到再交给父类加载器去加载,目的就是为了优先记载Web应用自己的类;

1.16 为什么Tomca要打破双亲委派机制模型?

Tomcat是web容器,那么一个容器就可能需要部署多个应用程序;

1、部署在同一个Tomcat上的两个Web应用所使用的java类库要相互隔离;

        比如说:一个项目使用了spring5的版本,一个项目使用了spring4的版本,两个项目版本不同,可能存在问题,所以不同的项目他们所需要的java类库需要相互隔离,所以需要不同的 加载器去进行记载;

2、部署在同一个Tomcat上的两个Web应用所使用的java类库要相互共享;

        也就是和上面相反,多个项目之间存在许多版本相同的java类库,重复加载放在元空间中会造成浪费,所以可以将tm都放在lib目录中进行加载,然后多个项目就可以共享lib中的jar包;

3、保证Tomcat服务器自身的安全不受部署的web应用程序的影响;

       Tomcat是由java写的,他自己在运行加载java类库的时候和部署的项目进行隔离,不让web项目影响到Tomcat自身的运行安全;(自己的webapp加载器,加载自己的web项目互不影响);

4、需要支持jsp页面的热部署和热加载;(不重启服务器让页面生效,其实就是启动了一个新的jsp记载器去加载jsp页面);当文件发生变化之后,就会启动一个新的jsp启动器加载;

1.17 有没有听说过热加载或热部署,如何自己实现一个热加载?

热加载:是指可以在不重启服务的情况员下让更改的代码生效,热加载看一看显著的提高开发以及调式效率。他是基于java的类加载器实现的;

热部署:是指可以在不重启服务的情况下重新部署整个项目,比如Tomcat热部署就是在程序运行时,如果我们修改了War包中的内容,那么Tomcat就会删除之前的War包解压的文件夹,重新解压新的War包生成新的文件夹;

热加载就是在运行时重新加载class,后台会启动一个线程不断检测你的class是否发生改变;

热部署是在运行时重新部署整个项目,耗时相对较高;

如何实现一个热加载?

1、实现自己的类加载器;

2、用自己的类加载器加载要热加载的类;

3、不断的轮训要加载的类class文件是否有更新,如果有更新,重新加载;(相当于一个监听的作用); 

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小馨java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值