【JVM之一入门】内存区域简介

1.总结java虚拟机怎么不先来说一下jvm是什么?

jvm是执行字节码文件的一个程序,对java字节码进行解释、运行,形成适应不同平台的机器码,从而是java语言能独立于各个不同的系统平台,如下的图能直观的看到我们java程序一步步成为不同的平台能执行的机器码的。

【JVM之一入门】内存区域简介

2.然而在jvm里面经历的过程是什么呢?首先我们看一下jvm里面的内存区域划分:

【JVM之一入门】内存区域简介

(1)程序计数器:(线程私有)

对于Java方法:记录的是正在执行的虚拟机字节码指令的地址

对于本地方法:计数器为空(undefined)

然而什么是Java方法,什么是本地方法呢?

java方法是java语言写的,编译成字节码,存在.class文件中的。

本地方法是其他语言写的,编译成与处理器相关的机器码,他是平台相关的,存储在动态链接库.dll文件(windows)。这样我们可以用本地方法直接访问底层操作系统的资源了,但是这个样子就变成了与平台相关了啊!所以java和其它语言混合编写的时候跨平台会受到限制啊!也就是我们为什么说JVM是有跨平台局限性的,但是运行在JVM上的纯java应用是跨平台的。这一方面是用了JNI接口具体实现java与其它语言的交互的。

(2)栈:分为虚拟机栈和本地方法栈。是方法执行的内存模型。栈里面的单位是栈帧。

【JVM之一入门】内存区域简介

(3)堆:是用于存放对象的内存区域。(垃圾回收的主要地方)

堆再怎么优化划分内存区域都是有一个终极的目标:实现对象的更快分配以及更好的回收内存

        1.从内存回收角度来看可以粗分为老年代,新生代。

        再细分可以分为 Eden、survivor from、survivor to(为了新生代的GC的复制算法设计的,老年代GC用标记-整理或者标记            清除算法)

        2.从内存分配的角度来看可以是从java共享的线程堆中划分出多个线程私有的分配缓冲区。

(4)方法区:用于存储已被加载的类的信息、常量、静态变量、即使编译器编译后的代码等。

在这里区域回收的地方主要是常量池的回收。

3.然而我们接着就会想了,我们创建对象的过程是怎么样的?是怎么分配堆里面的?还有我们怎么访问这个对象的呢?好了,可以一个一个来看。

(1)创建过程:new一个对象之后会检查指令的参数能否在常量池中找到该类的符号引用,检查该符号引用代表的类是否被加载、解析、初始化,若没有则加载

(2)内存分配:有两种方式:指针碰撞(指针向空闲的内存方向移动)、空闲列表(维护一个记录内存的列表)

(3)对象的内存布局:一个对象在内存中有对象头、实例数据、对齐补充 

(4)对象的访问定位:分为句柄式访问和直接指针访问,我们从下面的图中可以看到二者的区别。

【JVM之一入门】内存区域简介

【JVM之一入门】内存区域简介

我们可以看出直接指针比句柄方式多了一次指针的引用,访问的频繁的时候二者的差距会显现出来,但是句柄也是有的优点的就是reference存储的是稳定句柄地址,当一个对象移动了之后(GC),那么只改变句柄池中实例数据指针就可以了。

 

小白初学JVM,文章有什么错误,欢迎指正。