在这个身处互联网,高并发,高可用的软件世界里,后端人员,面对线上线下许多异常问题不知所措时,可以侧面从jvm的角度去排查问题了,当然了,如果不是java异常(网络原因或是其它)再用这样的方法去排查就有点…,哈哈,自行脑补。
讨论java虚拟机都听过一次编译,到处运行的说法吧,build once,run anywhere。
听过java作为高级语言(相对于汇编语言略微显得高级了些)可以实现跨平台,实际上跨平台的实现就是虚拟机帮我们做的。
手工写的程序或者称作代码机器是无法识别的,这就涉及到了如何将人能看懂的转成机器能识别的机器码操作流程了,在此不做分析,简单提下。
谈到jvm,主要说下java运行时数据区里面的基本组成部分即可,很详细的细节分析在此不做分析(手机写字很麻烦的)。
好了,我们先上图吧,有图好说话,有图有真相,啧啧。
ok,这次分享主要说下上面这个图的基本组成部分,个人见解,有什么问题欢迎各位大佬指正。
方法区method Area主要包含虚拟机加载的类信息,常量,静态变量以及即时编译器编译后的代码等数据。
jvm Stack虚拟机栈主要包含栈桢(stack Frame),栈桢对应着java的一个个方法,方法的调用和退出就对应着栈桢在虚拟机栈中的入栈和出栈的操作,后面分享一下栈的操作,关注公众号~后端新秀,后台私信即可领取。
本地方法栈native Method Stack,主要是为了调用类似C,C++方法而提供的了,这里有段故事,由于java刚起步时还是C++盛行的年代,为了向大佬C,C++靠近,用现在的话就有点…,无限遐想去吧,哈哈?,提供了这样的JNI。
程序计数器,主要的功能就是当做一个寄存器的作用,保存着字节码指令行号的地址,这里涉及到了操作系统时间片抢占的一些东西,在此不做讲述。
可以避免cpu由于时间片轮转来回切换时可以找到正确的位置。哈哈?,程序计数器是线程私有的,每个线程都有一个属于自己的程序计数器,程序计数器这块内存区域不会出现OOM现象,仅占用一小部分内存空间。
堆heap,主要存放对象的实例数据和数组对象,也称为GC堆,垃圾回收堆,由于内存的申请和销毁基本上不需要我们这批码农(程序员的标签我配不上?,你们可以昂)手动在程序中实现,完全依靠jvm自动实现,汗颜。所以内存的分配和回收部分不在此进行讲解。(手机打字很麻烦的)
堆主要分为新生代,老年代,这里的堆主要值得是java堆,主要指的是堆内,还有一部分是堆外空间,具体见后续文章说明吧,等到猴年马月?,新生代又分为伊甸区,S0,S1区,新生的对象主要先分配到伊甸园区,说明一下未必新生的对象都要预先分配到伊甸区,ok,解释一波哈,这主要对于占用内存较小的对象来说的,对于大对象而言就直接分配到老年代了,好了,涉及的内容太多了,三天三夜都说不完呀,捂脸。
堆是线程共享的,所以常常讨论的单机版服务数据一致性问题就需要在这里面考虑了,线程,操作系统执行的最小单元属于进程的一部分。
进程可以说是一个个程序,每个人都有对进程不同的说法,我这边将其描述为程序了,只不过线程属于进程的一部分,属于进程的一个子集而已。