您的位置:首页 > 编程语言 > Java开发

JVM内存结构

2017-01-06 00:00 232 查看
Java通过多线程机制使得多个任务同时执行处理,所有线程共享jvm的主内存,而每个线程都有自己的独立工作内存,当线程与内存区域进行交互时,数据从主存拷贝到工作内存,进而交由线程进行处理。

广义上的JVM内存可以分为:

JVM内存区域

名称存储内容
程序计数器jvm的指令信息
本地方法栈调用native的方法
JVM栈方法信息,基本类型实例
对象实例
堆外内存操作系统的内存,不受jvm影像
本地方法栈:这块区域主要是方便调用native方法使用

栈:我们常说的栈,主要存放方法信息,基本类型的实例和引用类型的引用。方法传递时,主要操作这块区,传递的是值,因为引用类型在栈中存储的是引用地址,所以对于引用类型来说,传递的是引用。栈是线程私有的,生命周期随着线程的生命周期进行变化。

堆:分为年轻代和老年代。年轻代里分为Eden和两个幸存者,对于小对象,直接被分配到Eden中,在GC回收时,优先回收Eden中不可达的对象,将可达对象放入到幸存者A,当幸存者A满时,可以到复制到B中,A,B可以相互复制。大的对象可以直接分配到老年代,经过几次垃圾回收后,新生代的对象会复制到老年代,老年代的对象保存的时间更久。

程序计数器:是一块较小的内存空间,他的作用是当前线程执行的字节码的行号指示器,通过改变计数器的值来选择下一个要执行的字节码指令,分支,循环等。由于jvm是多线程是通过线程切换并分配处理器执行时间来执行,在任何一个特定的时刻,一个核心只能执行一个线程,每个线程都需要独立的计数器,各条线程中的计数器互不影响,我们称为线程私有的内存。

方法区:存放类方法信息,及常量和静态变量,在Hotspot中称为永久代

堆外内存:在jdk1.4后引入了NIO 通过native函数直接分配堆外内存,然后通过存储在堆的directbytebuffer对象做为这个内存的引用。堆外内存的好处:不受jvm内存限制,只收到物理内存的限制。不消耗性能。通过参数-XX:MaxDirectMemorySize设置大小

堆外内存的GC:GC不能直接释放堆外内存,只能通过堆间接操作堆外内存,DirectByteBuffer对象在创建的时候关联了一个 PhantomReference,说到PhantomReference它其实主要是用来跟踪对象何时被回收的,它不能影响gc决策,但是gc过程中如果发现某个对象除了只有PhantomReference引用它之外,并没有其他的地方引用它了,那将会把这个引用放到 java.lang.ref.Reference.pending队列里,在gc完毕的时候通知ReferenceHandler这个守护线程去执行一些后置处理,而DirectByteBuffer关联的PhantomReference是PhantomReference的一个子类,在最终的处理里会通过Unsafe的free接口来释放DirectByteBuffer对应的堆外内存块
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java jvm