1.说一下jvm内存分为哪几个区域?哪些是线程独享?哪些是线程共享?
(1)JVM中线程私有的内存区:
a.程序计数器:当前线程所执行的字节码行号计数指示器,是线程私有的,即每个线程都有自己的程序计数器,需要注意的是,如果当前JVM执行的是Native代码(即非JAVA代码),那么程序计数器值为空
b.JAVA虚拟机栈:存放栈帧的地方,每个JAVA方法执行的时候会创建一个栈帧,该栈帧保持的是该方法的相关信息(局部变量表,操作数栈,方法出口等),栈帧随着方法的执行和跳出进栈和出栈
c.JAVA虚拟机栈是为JAVA方法提供服务的,而本地方法栈是为非JAVA方法提供服务的(Native方法)
(2)JVM中线程共享的内存区:
a.堆:存放对象实例的地方,从GC(垃圾回收)的角度讲,又分为新生代和老年代,属于线程共享的内存区域
b.方法区:储存已经被JVM加载的类信息,比如常量,静态变量,类的名称,即使编译器编译后的代码等数据。方法区中还包含运行时常量池,是动态的,可以在运行期间将新的常量放入池中。Class文件中也有常量池,用于存放编译器生成的各种字面量和符号引用,这部分内容会在类加载后进入方法区的运行时常量池中存放。
2.哪些内存区域会参与gc回收?
程序计数器,虚拟机栈,本地方法栈,都会随线程而生,随线程而灭,因此这几个区域的回收都具备确定性。
堆和方法区,只有在程序运行期间才可以知道会创建哪些对象,这部分内存的分配和回收是动态的,需要通过gc来回收。
(待完善)3.什么情况下一个对象会被gc掉?为什么要在这个时候让对象被gc?
当新生代eden区和老年代没有足够空间进行分配时会触发对象的GC,并且对进行可达性分析的时候,该对象没有GCRoots对象引用他,则他会被回收掉。因为空间不足,需要回收掉一部分内存才可以有足够空间可以分配。
4.何时触发minor gc?何时触发full gc?
5.如何自定义自己的类加载器?
继承ClassLoader ,重写findClass()方法,调用defineClass()方法
6.自定义类加载器的作用
jvm自带的三个加载器只能加载指定路径下的类字节码。如果某个情况下,我们需要加载应用程序之外的类文件呢?比如本地D盘下的,或者去加载网络上的某个类文件,这种情况就可以使用自定义加载器了。
7.以下两种类加载方式有什么区别?class.forName()和classLoader?
ClassLoader类加载器,主要的作用是将class文件加载到jvm虚拟机中。jvm启动的时候,并不是一次性加载所有的类,而是根据需要动态去加载类,主要分为隐式加载和显示加载。
隐式加载:程序代码中不通过调用ClassLoader来加载需要的类,而是通过JVM类自动加载需要的类到内存中。例如,当我们在类中继承或者引用某个类的时候,JVM在解析当前这个类的时,发现引用的类不在内存中,那么就会自动将这些类加载到内存中。
显示加载:代码中通过Class.forName(),this.getClass.getClassLoader.LoadClass(),自定义类加载器中的findClass()方法等。