标签:
第一部分 走进Java
第二部分 自动内存管理机制
第2章 垃圾收集器与内存分配策略
1.Java虚拟机在执行java程序时会把它锁管理的内存会分为若干个不同的数据区域,
这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,
有些区域则是在以来用户线程的启动和结束而建立和销毁。
根据《Java虚拟机规范》,包括以下几个运行时数据区域:
程序计数器(Program Counter Register)
方法区(Method Area)
虚拟机栈(VM Stack)
本地方法栈(Native Method Stack)
堆(Heap)
2.PCR 程序计数器
//在操作系统中学习过Program Counter,程序计数器是用于存放下一条指令所在单元的地址的地方。
在虚拟机中,可以看做是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转等基础功能都需要依赖计数器完成。
为了多线程切换过程中能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间的计数器互不影响,独立存储,成为“线程私有”的内存。并且,程序计数器是唯一一个在Java虚拟机规范中没有规定任何OutOfMemory情况的区域。
3.Java虚拟机栈 Java Virtual Machine Stacks
与程序计数器一样,Java虚拟机栈也是线程私有的,生命周期和线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧,用于存储局部变量表,操作栈,动态链接,方法出口等信息。
//每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出站的过程。
虚拟机栈会抛出 StackOverFlowError 和 OutOfMemoryError异常。
4.本地方法栈 Native Method Stacks
虚拟机栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
5.Java堆
Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此区域的唯一目的就是 存放对象实例。
Java堆是垃圾收集器管理的主要区域,很多时候被称为“GC堆(Garbage Collected Heap)”。
如果在堆中没有内存完成实例分配,并且无法继续扩展时,会抛出OutOfMemoryError异常。
6.方法区
方法区和Java堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据,
//运行时常量池,是方法区的一部分。
7.直接内存 Diret Memory
直接内存并不是Java虚拟机规范中定义的内存区域,但是频繁使用,也可能导致OutOfMemoryError异常出现。
NIO的部分操作,使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆里面的DirectByteBuffer对象,作为这块内存的引用进行操作,避免了在Java堆和Native堆中来回复制数据,一些场景中可以显著提高性能。
8.主流的对象访问方式,使用句柄和直接指针。
使用句柄访问方式的好处就是reference中存储的是稳定的句柄地址,在对象被移动时只会改变句柄中的实例数据指针,而reference本身不需要被修改。
使用指针访问速度更快,节省了一次指针定位的时间开销。
第3章 虚拟机性能监控与故障处理
//了解GC和内存分配有哪些意义?
当需要排查各种内存溢出、内存泄露问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,就需要对这些“自动化”的技术实施必要的监控和调节。
1.引用计数算法
给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;引用失效时,计数器值减1‘任何时刻计数器都为零的对象就是不可能再被使用的。
但是,引用计数法有一个很大的不足,很难解决对象之间的相互循环引用问题。
下面的代码描述了引用计数法的一个情景:
public class ReferenceCountGC { public Object instance=null; private static final int _1MB=1024*1024; private byte[] bigSize=new byte[2*_1MB]; public static void testGC(){ ReferenceCountGC objA=new ReferenceCountGC(); ReferenceCountGC objB=new ReferenceCountGC(); objA.instance=objB; objB.instance=objA; objA=null; objB=null; } }
如果单纯的通过引用计数法来判断对象的状态,因为互相循环引用,这两个对象都不会被GC回收。
2.根搜索算法
通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,当到达不在GC Roots引用链上的对象时,即使它们之间互相关联,仍然判定为可回收对象。
用图论的理论,可以表示为GC Roots到该对象不可达。
3.更好的理解“引用”
Java中的引用,最开始的定义很传统:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表着一个引用。
这样的定义在垃圾收集时太过绝对,后来对引用的概念进行了扩充,将引用分为强引用,软引用,若引用,虚引用,四种引用强度逐渐减弱。
《深入理解Java虚拟机:JVM高级特性与最佳实践》学习笔记 Ⅰ
标签:
原文地址:http://www.cnblogs.com/binyue/p/4303214.html