JVM内存区域详解

运行时数据区域

  1. 程序计数器 : (线程隔离) 较小的内存空间 当前线所执行的字节码的行号指示器。执行的java方法 表示 当前执行的字节码的指令地址 执行的是native方法 就是为空(undefined)
  2. java虚拟机栈 : (线程隔离) 每次执行方法会创建一个栈帧 局部变量表(一组变量值的存储空间 存放方法的参数和方法内部定义的局部变量 以Slot为单位 非static的方法 0位置就是this 局部变量表的共享机制 在大内存分配的时候 手动设置 null ) 操作数栈(方法执行运算 最大深度 在编译的时候 max_stacks) 动态链接 (调用的方法 静态链接 或者 动态链接 ) 方法出口(返回上层方法执行的状态 异常的时候就会有 异常处理器表)等
  3. 运行时常量池:方法区的一部分 编译期 class的符引用 运行时候就变成直接引用
  4. 直接内存 :对外内存 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字节的倍数
  1. 对象的访问定位 : 句柄和直接指针(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 当引用失效时计数器值就减1 当为0时表示对象不在被引用 ,简单高效 但是 很难解决对象之间循环引用的问题
  2. 可达性分析算法:通过一系列称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,搜索路径称为 “引用链”,以下对象可作为GC Roots(就是找到根):
    • 虚拟机栈 (栈中的本地变量表)中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • Native方法引用的对象
  3. 引用的的分类
    • 强引用 :只要存在就不会被回收
    • 软引用 : SoftReference 描述一些还有用的但并非必须的对象。对于软引关联着的对象 在系统发生内存溢出钱,会把这些对列进回收范围 (BundleReference)
    • 弱引用 : WeakReference 无论内存是否足够 都会回收掉被弱引用关联着的对象(CacheKey)
    • 虚引用: PhantomReference 最弱的一种关系 目的:就是这个关联虚引用的对象被垃圾回收时得到一个系统通知(Cleaner ByteBuffer 回收直接内存)
  4. 生存还是死亡 :真正的宣告一个对象的死亡最少经历2次被标记的过程
    • 如果对象进行可达性分析后发现没有GCroots相关联 被标记为第一次筛选 当对象没有覆盖finalize方法或者已经调用过了 如果有必要执行就放到F-Queue中等待执行 创建一个低优先级的 Finalizer线程去执行他
  5. 回收方法区 :废弃的常量和无用的类 :
    • 该类所有的实例都被回收 java堆中不存在任何的实例
    • 加载该类的ClassLoader已经回收
    • 该类对应的Class对象没有任何地方引用 无法在任何地方通过反射访问该类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值