运行时数据区域
- 程序计数器 : (线程隔离) 较小的内存空间 当前线所执行的字节码的行号指示器。执行的java方法 表示 当前执行的字节码的指令地址 执行的是native方法 就是为空(undefined)
- java虚拟机栈 : (线程隔离) 每次执行方法会创建一个栈帧 局部变量表(一组变量值的存储空间 存放方法的参数和方法内部定义的局部变量 以Slot为单位 非static的方法 0位置就是this 局部变量表的共享机制 在大内存分配的时候 手动设置 null ) 操作数栈(方法执行运算 最大深度 在编译的时候 max_stacks) 动态链接 (调用的方法 静态链接 或者 动态链接 ) 方法出口(返回上层方法执行的状态 异常的时候就会有 异常处理器表)等
- 运行时常量池:方法区的一部分 编译期 class的符引用 运行时候就变成直接引用
- 直接内存 :对外内存 MaxDirectMemorySize
HotSpot虚拟机对象
1.对象的创建 : 1.类的符号引用 2.在java堆中分配(指针碰撞 空闲列表 CAS重试) 3.初始化 元数据信息 除了对象头其他的都是0 4.执行
2.对象的的内存布局 : 对象头 实例数据 对齐填充
- 对象头 对象自身运行的临时数据 (哈希码 GC分代年龄 锁标志 线程持有的锁 偏向锁的ID 偏向时间戳等)简称Mark Word 32bit 和64bit 是一个非固定的数据结构
- 未被锁定的情况下 32bit ==> 25bit的哈希码 4bit的对象分代年龄 2bit存储锁标志 1bit固定为0 (2bit ==> 01 未锁定 00 轻量级锁 10 膨胀(重量级锁)11 GC标记 01 可偏向)
- 对象头的另外一部分是类型指针 即指向它的元数据的指针 通过这个指针来确定这个对象是哪个类的实例 如果对象是一个java数组 还必须有一块用于记录数据的长度
- markOop.hpp
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
//
// 64 bits:
// --------
// unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
// PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
// size:64 ----------------------------------------------------->| (CMS free block)
//
// unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
// JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
// narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
// unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)
- padding 消除伪缓存 必须是8字节的倍数
- 对象的访问定位 : 句柄和直接指针(sun hotspot)
参数设置
- 堆的设置 : 堆内存 栈内存 堆外内存(方法区(常量池 JIT的变量的代码 1.8可以自动扩展元空间) 直接内存 Direct (可以调用api分配 jvm回收,是回调api回收) 自己调用unsafe 等api分配的(不受jvm控制))
-Xms4096m -Xmx4096m -XX:PermSize=512M -XX:MaxNewSize=512m -XX:MaxPermSize=512m -XX:MaxDirectMemorySize=5M - 设置分代信息和垃圾收集器
-XX:NewRatio=16 -XX:+UseAdaptiveSizePolicy - 设置gc
-verbose:gc -Xloggc:gc.log -XX:+PrintGCDetails -Xloggc:temp_gc.log -XX:+PrintGCDetails -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -XX:+PrintReferenceGC - 异常dump,错误日志文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=d:\dump\test.hprof -XX:ErrorFile=/path/hs_error%p.log - 其他性能优化和辅助型
-XX:+DisableExplicitGC -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining
http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html
垃圾收集器和内存分配策略
GC的本质 : 1. 哪些内存需要回收 2. 什么时候回收 3.如何回收
- 引用计数法 :每当有一个地方引用它时候 计数器值就加1 当引用失效时计数器值就减1 当为0时表示对象不在被引用 ,简单高效 但是 很难解决对象之间循环引用的问题
- 可达性分析算法:通过一系列称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,搜索路径称为 “引用链”,以下对象可作为GC Roots(就是找到根):
- 虚拟机栈 (栈中的本地变量表)中引用的对象
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
- Native方法引用的对象
- 引用的的分类
- 强引用 :只要存在就不会被回收
- 软引用 : SoftReference 描述一些还有用的但并非必须的对象。对于软引关联着的对象 在系统发生内存溢出钱,会把这些对列进回收范围 (BundleReference)
- 弱引用 : WeakReference 无论内存是否足够 都会回收掉被弱引用关联着的对象(CacheKey)
- 虚引用: PhantomReference 最弱的一种关系 目的:就是这个关联虚引用的对象被垃圾回收时得到一个系统通知(Cleaner ByteBuffer 回收直接内存)
- 生存还是死亡 :真正的宣告一个对象的死亡最少经历2次被标记的过程
- 如果对象进行可达性分析后发现没有GCroots相关联 被标记为第一次筛选 当对象没有覆盖finalize方法或者已经调用过了 如果有必要执行就放到F-Queue中等待执行 创建一个低优先级的 Finalizer线程去执行他
- 回收方法区 :废弃的常量和无用的类 :
- 该类所有的实例都被回收 java堆中不存在任何的实例
- 加载该类的ClassLoader已经回收
- 该类对应的Class对象没有任何地方引用 无法在任何地方通过反射访问该类