什么是JVM
谈谈你对JVM得理解
jdk1.8之后JVM有什么改变
-
JVM的体系结构图
2.java虚拟机自带的类加载器
启动类加载器(Bootstrap) C++
扩展类加载器(Extension) Java
应用程序类加载器(AppClassLoader)Java,也叫系统类加载器,加载当前应用的classpath的所有类。
3.什么是classLoader的双亲委派机制
当一个类收到了类加载的请求时,他首先不会尝试自己去加载这个类,而是要把这个加载请求委派给父类去完成,每一层的类加载器都会如此,因此所有的加载请求都会传给启动类加载器,只有当父类加载器反馈出无法完成这个请求时(父类加载路径下没有找到需要加载的Class),子类的加载器才会自己去加载。
采用双亲委派的一个好处是:如果要加载rt.jar包中的java.long.Object类,不管是哪个加载器要加载这个类,都会把加载请求委派给顶层的启动类加载器进行加载,这样就能保证不同的类加载器加载到的是同一个Object对象。4.Native Method Stack(本地方法栈)
用来等级native方法,Engine执行时加载本地方法库。5.Native Interface(本地接口)
本地接口用来融合其他语言为Java所用,初衷是为了融合C和C++,在内存中专门开辟了一块区域来处理标记为native的代码,具体做法是在本地方法栈中登记native方法,在Execution Engine执行时加载native libraries。6.PC寄存器
也叫程序计数器。是每个线程的程序计数器,是线程私有的,相当于一个指针,指向方法区中的方法字节码(用来存储指向下一条指令的地址),由执行引擎读取下一条指令,占用的空间很小,可以忽略不计。7.Method Area(方法区)
用来存储类的结构信息。是线程之间共享的运行时内存区域。比如存储运行时常量池,字段,方法数据,构造函数和普通方法的字节码内容。(实例变量存储在堆中,和方法区无关)
方法区也可以看作是一种规范,在不同版本的虚拟机里的实现不一样,比较典型的就是永久代和元空间。8 stack
栈管运行,堆管存储
栈是主管程序运行的一种结构,在线程创建时创建,线程结束就释放,是线程私有的,所以不存在垃圾回收。8种基本类型,对象的引用类型变量,实例方法都是存储在栈内存中。9 Heap 堆
一个JVM实例只存在一个堆空间,堆空间的大小是可以改变的,在逻辑上分为了新生代,老年代和元空间。类加载器在读取了类文件之后,会将类,方法,常变量放到堆内存中,保存所有类的真实信息,一边执行器执行。
从物理层面角度分析,堆内存分为了新生代和老年代,并且各占不同的比例。
当Eden区放满的时候会触发第一次GC,GC之后会将存活的对象拷贝到from区,当eden区再次触发GC时会扫描eden区和from区,对这两个区内的对象进行垃圾回收,然后将存活的对象复制到to区,并把这些对象的年龄+1。(如果有年龄达到老年标准的对象,则将对象移动到老年代)。
之后清空eden区和from区,并将from区和to区进行互换,第二次GC结束之后的to区就会成为第三次GC时的from区。
经过这样来回的复制,存活的对象的年龄会不断增加,当年龄达到15时,就能进入老年代。这个参数是由JVM的MaxTenuringThreshold来决定的。
再谈谈永久代,jdk1.8之后叫元空间,这是一个逻辑上的内存区域。可以当作是方法区的一种实现,用来存放JDK本身携带的类,接口等元数据信息,加载进该区域的数据不会被垃圾回收器清理,只有JVM关闭之后才会释放掉。