jvm内存模型
Student st = new Student()
- 线程共享 生命周期随着jvm; 垃圾回收
- 堆 对象 成员变量 new Student()
- 方法区 JIT(类编译后)数据;加载类的类定义数据;常量和静态变量(1.8以后也是放在堆中的); 运行时常量池
- 非线程共享 生命周期随着线程
- jvm栈 实例 4个字节的引用地址 栈帧 先进后出
- 局部变量表
- 操作数栈 中间值
- 帧数据区 常量池指针 异常 返回信息
- 程序计数器 记录程序的调整
- 本地方法栈 native
- jvm栈 实例 4个字节的引用地址 栈帧 先进后出
对象内存分配(堆)
- 对象头
- 运行时数据 Mark Word lock 故synchronized实现的同步锁,真实名称叫做重量级锁 ,锁的是对象 4
- 类型指针 4
- 实例数据(对象体)保存对象属性和值
- 对齐补充(8的倍数)
类加载机制
- 加载 .class中的二进制读入内存 方法区
- 连接
- 验证 验证是否是正确结构
- 准备 方法区分配内存 给静态变量赋默认值(0);静态常量赋值
- 解析 符号引用转直接引用
- 初始化 静态变量初始化 4种情况必须初始化
- new
- 反射
- 子类初始化时父类
- main方法所在类jvm启动时
- 使用
- 卸载
垃圾回收算法
- 引用计数法
- 最古老算法
- 引用计数器
- 循环引用问题
- 标记清除法 CMS收集器
- 有碎片,不连续;大对象有可能在最后才找到合适的空间
- 复制算法 Parallel Scavenge 收集器
- 年轻代
- 占一半空间
- 标记整理算法 Serial Old 收集器 Parallel Old 收集器
- 将保留的整理到一起,有移动
- 不会产生碎片
- 老年代使用
- 分代算法
- 不同分代采用不同的回收算法
- 分区算法
- 分成多个独立小区,按需回收
垃圾收集器
- 串行收集器
- 并行收集器
- G1收集器
JVM常用参数
执行语法:
Java [-options] [package+className] [arg1,arg2,…,argN]
options:
-Xms128m 设置初始化堆内存为128M
-Xmx512m 设置最大堆内存为512M
-Xmn160m 设置新生代大小为-Xmn160M(堆空间1/4~1/3)
-Xss128m 设置最大栈内存为128M
-XX:SurvivorRatio 设置新生代eden区与from/to空间的比例关系
-XX:PermSize=64M 设置初始永久区64M
-XX:MaxPermSize=128M 设置最大永久区128M
-XX:MaxMetaspaceSize 设置元数据区大小(JDK1.8 取代永久区)
-XX:+DoEscapeAnalysis 启用逃逸分析(Server模式)
-XX:+EliminateAllocations 开启标量替换(默认开启)
-XX:+TraceClassLoading 跟踪类的加载
-XX:+TraceClassUnloading 跟踪类的卸载
-Xloggc:gc.log 将gc日志信息打印到gc.log文件中
options:
-XX:+PrintGC 打印GC日志
-XX:+PrintGCDetails 打印GC详细日志
-XX:+PrintGCTimeStamps 输出GC发生的时间
-XX:+PrintGCApplicationStoppedTime GC产生停顿的时间
-XX:+PrintGCApplicationConcurrentTime 应用执行的时间
-XX:+PrintHeapAtGC 在GC发生前后,打印堆栈日志
-XX:+PrintReferenceGC 打印对象引用信息
-XX:+PrintVMOptions 打印虚拟机参数
-XX:+PrintCommandLineFlags 打印虚拟机显式和隐式参数
-XX:+PrintFlagsFinal 打印所有系统参数
-XX:+PrintTLAB 打印TLAB相关分配信息
-XX:+UseTLAB 打开TLAB
-XX:TLABSize 设置TLAB大小
-XX:+ResizeTLAB 自动调整TLAB大小
-XX:+DisableExplicitGC 禁用显示GC (System.gc())
-XX:+ExplicitGCInvokesConcurrent 使用并发方式处理显式GC
双清委派机制
- 好处
- 安全 避免随意篡改核心类
- 去重
- 自定义类加载器
- 重载findClass()方法 不会打破双清委派机制
- 重写整个loadClass()方法 打破双清委派机制
- 双清委派机制破坏者---线程上下文加载器(contextClassLoader):
// ContextClassLoader默认存放了AppClassLoader的引用 public static <S> ServiceLoader<S> load(Class<S> service) { // 通过线程上下文加载器获取 ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); }