在以前已经对Java的字节码进行了很是详细而又系统的学习了,接下来开启jvm内存相关的新篇章,在一个新知识开头以前确定得理论化的对其进行一个总体的介绍,因此摒弃浮躁,先来看看相关的理论,主要是看一下JVM内存的相关结构:html
虚拟机栈:每个方法在执行的过程当中都会生成一个栈帧(Stack Frame,在以前【http://www.javashuo.com/article/p-nvbhpevw-dt.html】已经有介绍过)这个数据结构。web
程序计数器(Program Counter):它占据的空间是比较小的,主要是描述线程执行字节码第一行执行完了以后,下一行字节码在哪。数据结构
本地方法栈:主要用于处理本地方法。jvm
堆(Heap):这是JVM所管理最大的内存空间,在Java当中咱们都是通用引用来操做对象的,而对象自己是位于堆上面,而引用则是位于虚拟机栈上面,因此引用自己是个变量,因此在Java中必定是经过引用来获取到这个对象而后去操纵它。下面用一个小的示意图来理论引用与对象它们之间的关系。学习
其实引用指向对象是有两种形态的,上面只是一个粗略的形态,其实在堆中一部份存放的是对象实例自己的数据,另外一部分则是元数据(也就是class数据),而元数据只有一份,它是存放在另一个位置的,该位置叫方法区,以下:线程
而实际实现第一种形态多是这样:指针
而第二种形态可能为:htm
对于Oracle的Hotspot虚拟机采用的是第二种形态,那对于这二种形态有啥区别呢?其实区别仍是挺大的,对于JVM垃圾回收来讲,当对像被回收以后可能会形成对象的移动,用个形象的未例图来表述这个移动:对象
对于对象的移动,假如采用第一种形态,因为是用一个指针来指向对象,因此指针的值也会发生变化,而对于堆内存而言发生垃圾回收的频率是至关之高的,因此该指向变量的指针会频繁发生变化;而若是采用第二种形态则没有这个问题,由于ref是直接指向的对象自己,当对象移动时则ref只是指向的位置会发生变化,值仍是同样的,以下:blog
因此通过对比,也能发现第二种形态会更好,这也是Oracle的Hotspot为啥采用第二种的缘由。
方法区(Method Area):存储元信息。咱们对于垃圾收集器可能常常会听到一个叫永久代(Permanent Generation)的概念,因此永久代固然就是不多会被回收,因此会将方法区称为永久代,可是从JDK1.8开始,已经完全废弃了永久代了,使用元空间(Meta Space)代替。
运行时常量池:方法区的一部内容,这个在我们以前的字节码学习中已经详细学习过。
直接内存:Direct Memory,它并非由JVM所管理的一块区域,而是由系统所管辖的,只不过是JVM向系统申请了这块内存。
以上是从宏观的角度来审视JVM的内存结构,在以后会结合实践对这些理论进行进一步巩固!