
本文转载自公众号:石杉的架构笔记
写在前面
大家好,我是专栏《从零开始带你成为JVM实战高手》的作者,外号救火队队长,目前在阿里任职。
下面,我整理了JVM典型的30个问题,并给出了解答,大家可以仔细看看,认真思考,看是不是你也对这些问题曾经有过疑惑?
问题一


问题二

2.新建的实例在堆内存,实例变量也是在堆内存? 是这样吗?

问题三

入栈的时候,就是你执行一个方法的时候,为这个方法创建一个栈帧入栈
出栈,就是你的方法执行完毕了,就会出栈,其实这个不用急,明天的文章会有详细的图解,你会看明白的。

问题四


问题五

类加载器有三层,如果在第二层的类加载器可以加载这些类的话,就没有必要往上去找他的父类加载吗?
既然说类只有用到的时候才加载到内存中,那么new对象的时候肯定用到,但是是不是先经历过类的所有过程才将类实例化?

问题六


问题七


问题八


问题九


问题十

其实关于这个问题,不用过于纠结,每一层类加载器对某个类的加载,上推给父类加载器,到顶层类加载器,如果发现自己加载不到,再下推回子类加载器来加载,这样可以保证绝对不会重复加载某个类。
至于为什么不直接从顶层类加载器开始找,那是因为类加载器本身就是做的父子关系模型
你想一下Java代码实现,他最底下的子类加载器,只能通过自己引用的父类加载器去找。如果直接找顶层类加载器,不合适的,那么顶层类加载器不就必须硬编码规定了吗?
这就是一个代码设计思想,保证代码的可扩展性。

问题十一


问题十二


问题十三

class文件分配内存是在准备阶段,那类的class对象是在准备阶段创建的吗?
如果实例变量有初始值,那实例变量是和类变量一同在初始化阶段赋值的吗?
初始化之后是不是就有实例了
类是在准备阶段分配内存空间的
实例变量得在你创建类的实例对象时才会初始化
类的初始化阶段,仅仅是初始化类而已,跟对象无关,用new关键字才会构造一个对象出来

问题十四


问题十五


问题十六


问题十七

用户使用类的时候应该是希望类已经准备好了一些数据,我猜想jvm设计者设计先执行static代码块的机制,是希望开发者在这里把使用类之前需要准备的工作在这里准备好
为什么类的初始化需要执行静态代码块,给静态成员变量赋值,是因为这些数据是在方法区吗?
启动类、扩展类和自定义加载器都已经指定了加载路径,所以不应该会有重复加载类的问题吧,所以双亲委派是不是没有必要
没错,必须有初始化过程,准备好类级别的数据
双亲委派,避免重复加载,评论区里多次回复了这个问题,可以看一看

问题十八

其实初始化时机就是对类的主动使用:调用静态方法时对类的主动使用的一种场景,main方法本质上是个static方法,没有调用的main方法和没有调用的static方法没区别!
有一个问题,包含main方法的类会优先加载,如果一个项目中有多个类中都有main方法,都会加载么?

问题十九

tomcat本身是java程序,那么tomcat的实现程序的class是由应用类加载器加载的,用户自己的java程序war包,放入tomcat的程序的classpath中
这样用户的程序和tomcat的程序都是由应用类加载器加载了,也就是处于一个jvm中了

问题二十


问题二十一

为什么类的初始化需要执行静态代码块,给静态成员变量赋值,是因为这些数据是在方法区吗?
启动类、扩展类和自定义加载器都已经指定了加载路径,所以不应该会有重复加载类的问题吧,所以双亲委派是不是没有必要
没错,类在方法区,他在内存里,所以你必须给他初始化,赋值
还是有必要,比如启动类加载器,可以通过一些方式指定加载其他目录的类,那么你必须得走双亲委派,如果对那些特殊区域的类加载,走双亲委派,才能上推到启动类加载器去执行,不会重复加载

问题二十二

好处就在于,每个层级的类加载器各司其职,而且不会重复加载一个类。
比如你代码里用两个不同层级的类加载器,都去尝试加载了某个类,如果有双亲委派机制,那么都会先找父类加载器去加载,如果加载到了,那么以后就只会是他去加载这个类。
否则如果没有双亲委派机制,那么岂不是两个不同层级的类加载器可以加载同一个类,造成类的重复加载!

问题二十三


问题二十四

假设一个背景在Tomcat部署系统的话,那么动态部署,也成为热部署
就是直接系统放入Tomcat对应目录,他自动就重新加载你最新的代码给你热部署了,不需要对Tomcat进行停机再重启;
反之,则是先停止Tomcat,然后部署最新代码到Tomcat对应目录里,然后重启Tomcat

问题二十五

没错,明天更新的第三篇文章里,会讲解类加载机制,rt.jar这属于核心类库,属于支撑我们Java系统运行的底层类库,所以他一定会被加载
我们自己写的代码,一般是你代码运行使用到了哪个类,就会去加载哪个类

问题二十六


二十七


问题二十八


问题二十九


问题三十

可以的,比如jvmti小工具就可以实现class文件的加密
另外其实为了保护源代码安全,有很多商业公司推出了专业级别的class加密产品,可以付费使用。
解密的话一般可以基于自定义的类加载器来实现,在加载类的时候把class给解密,这样就可以保护自己的源代码安全了。

最后,附上两张Tomcat类加载如果按委派模型的加载流程和实际实现的流程(专栏读者所画)


这些,就是本周展示的典型问题了。你都理解了吗?
作者:中华石杉,十余年BAT架构经验倾囊相授。个人微信公众号:石杉的架构笔记(ID:shishan100)
长按订阅更多精彩▼
如有收获,点个在看,诚挚感谢

