JVM体系结构及优化
源文档:https://docs.oracle.com/javase/8/docs/technotes/guides/vm/index.html
JVM体系结构 方法区,类加载器,堆,Java栈,本地方法栈,程序计数器,执行引擎,PC寄存器。
类加载器:
• 启动类加载器 (Bootstrap Bootstrap)
• 扩展类加载器 (Extension Extension Extension)Java Java
• 应用程序类加载器应用程序类加载器 应用程序类加载器 (AppClassLoader AppClassLoader AppClassLoader ) Java
也叫系统类加载器,加载当前应用的classpath的所有类的所有类
• 用户自定义加载器JJava.lang.ClassLoader的子类,用户可自定义
类的加载步骤:
- 效验:检查class文件的正确性,安全性
- 准备:为类变量分配存储空间并设置类变量初始值,类变量随类型信息存放在方法区中,生命周期很长,使用不当和容易造成内存泄漏。
- 解析:jvm将常量池内的符号引用转换为直接引用
分析ClassLoader.loadClass和Class.forName的区别
反射实现的方式及原理?
PC寄存器:
- 程序计数器是一块较小的内存空间 程序计数器是一块较小的内存空间,当前线程所执行的字节码是当前线程所执行的字节码是当前线程所执行的字节码的行号指示器
- 程序计算器处于线独占区
- 如果线程执行的是 java方法,记录的是正在执行虚拟的字节码指令的地址,如果是native方法,这个计数器的值为undefined
栈区:
- 栈也叫内存 ,主管 Java 程序的运行 ,是在线程创建时创建 ,它的生命期是跟随线程,线程结束栈内存也就释放,对于栈来说不存在垃圾回收问题 ,只要线程一结束该栈就Over 生命周期和线程一致,是线程私有的 。8种基本类型的变 量+对象的引用变量 +实例方法都是在函数的栈内存中分配 。
栈存储什么 ?
- 局部变量表 :输入参数和出以及方法内的变量 类型;局部表在编译期间完成分配,当进入一个方法时这帧中多少内存是固定的
- 栈操作( Operand Stack ):记录出栈、入的操作;
- 动态链接
- 方法出口
- 栈溢出 StackOverflowError,OutOfMemory
方法区:
Method Area 方法区是被所有线程共享 ,所有字段和方法节码 ,以及一些特殊方法如构造函数 ,接口代码也在此定义 。简单说 ,所有定义的方法信息都保存在该区域 ,此区属于共享间。 类信息 类的版本字段方法接口
- 静态变量
- 常量
- 类信息 (构造方法 /接口定义 )
- 运行时常量池
方法区与永久代
方法区永久存储区是一个常驻内域,用于放 JDK 自身所携带的 Class,Interface 的元数据,也就是说它存储运行环境必须类信息被装载进此区域不会被垃圾回收器掉的,关闭JVM才会释放此区域所占用的内存。如果出现java.lang.OutOfMemoryError:PermGen space,说明是Java 虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。
- Jdk1.6 及之前: 有永久代 , 常量池 1.6 在方法区
- Jdk1.7 : 有永久代,但已经逐步“去”,常量池 1.7 在堆
- Jdk1.8 及之后: 无永久代,常量池 1.8 在元空间
常量池问题<待续>
堆:
一个 JVM 实例只存在一个堆内,堆内存的大小是可以调节的.类加载器读取了文件后,需要把类,方法,常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器,堆内存分为三部:
- Permanent Space Permanent Space 新生区 Young/NewYoung
- Tenure generation space 养老区 Old/ Tenure Old
- Permanet Space 永久区 Perm
堆JDK7和JDK8之间的关系和差异
对象的创建流程
堆,栈,方法区的交互关系
内存的分配策略:
- 优先分配Eden区
- 大对象直接分配到老年代 -XX:PretenureSizeThreshold
- 长期存活的对象分配老年代 -XX:MaxTenuringThreshold=15
- 空间分配担保 -XX:+HandlePromotionFailure
检查老年代最大可用的连续空间是否于历次晋升到年代对象的平均大小。
- 动态对象年龄如果在Survivor空间中相同年龄所有对象大小的总和于 Survivor空间的一半,年龄大于或等该的对象就可以直接进入老代
-XX:TargetSurvivorRatio
性能调优
如何判断对象为垃圾对象?
- 引用计数法
- 可达性分析法
如何回收?
何时回收?
垃圾回收算法
- 引用计数法
- 复制算法
- 标记清除
- 标记整理
- 标记清除压缩
垃圾回收器
- CMS
- Serial
- G1
G1收集器通过多种技术实现了高性能和暂停时间目标。
堆被分区为一组大小相等的堆区域,每个区域都是一个连续的虚拟内存区域(region)。G1执行并发全局标记阶段以确定整个堆中对象的活跃度。在标记阶段完成之后,G1知道哪些区域基本上是空的。它首先收集在这些区域,这通常会产生大量的自由空间。这就是为什么这种垃圾收集方法称为Garbage-First。顾名思义,G1将其集合和压缩活动集中在堆的可能充满可回收对象的区域,即垃圾。G1使用暂停预测模型来满足用户定义的暂停时间目标,并根据指定的暂停时间目标选择要收集的区域数。
由G1确定为回收成熟的区域是使用疏散收集的垃圾。G1将对象从堆的一个或多个区域复制到堆上的单个区域,并且在此过程中压缩并释放内存。这种疏散在多处理器上并行执行,以减少暂停时间并提高吞吐量。因此,对于每次垃圾收集,G1会持续工作以减少碎片,在用户定义的暂停时间内工作。这超出了以前两种方法的能力。CMS(Concurrent Mark Sweep)垃圾收集不进行压缩。ParallelOld垃圾收集仅执行整堆压缩,这会导致相当长的暂停时间。
值得注意的是G1不是实时收集器。它以高概率但不是绝对确定性满足设定的暂停时间目标。基于先前集合的数据,G1估计可以在用户指定的目标时间内收集多少个区域。因此,收集器具有收集区域的成本的相当准确的模型,并且它使用该模型来确定在停留在暂停时间目标内时要收集哪些区域和多少区域。
Oracle JDK 7 Update 4及更高版本完全支持Garbage-First(G1)垃圾收集器。G1收集器是一种服务器式垃圾收集器,适用于具有大容量存储器的多处理器机器。它以高概率满足垃圾收集(GC)暂停时间目标,同时实现高吞吐量。全堆操作(例如全局标记)与应用程序线程同时执行。这可以防止与堆或实时数据大小成比例的中断。
- ParNew
- ZGC
虚拟机工具:
- 查看JVM信息:
C:\Users\Administrator>jinfo -flags 10276
Attaching to process ID 10276, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Non-default VM flags: -XX:CICompilerCount=3 -XX:ConcGCThreads=1 -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=268435456 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=643825664 -XX:MinHeapDeltaBytes=1048576 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation -XX:+UseStringDeduplication
Command line: -Dosgi.requiredJavaVersion=1.8 -Dosgi.instance.area.default=@user.home/eclipse-workspace -XX:+UseG1GC -XX:+UseStringDeduplication -Dosgi.requiredJavaVersion=1.8 -Dosgi.dataAreaRequiresExplicitInit=true -Xms256m -Xmx1024m -javaagent:D:\eclipse\project\eclipse\lombok.jar
jps:java process status
jps -l 主类全名
jps -m 运行传入主类的参数
jps -v 虚拟机参数
Class文件结构分析:
最新文章
- java第一天学习作业及答案
- 关于16年2月14日以后上传AppStore出现:Missing iOS Distribution signing identity for...的问题
- docker ui
- WebRequest 获取网页乱码
- Python: 关于nose
- 对Memcached使用的总结和使用场景
- 能发送http请求(get,post)的工具
- MongoDB学习笔记06
- 原型扩展的方法解决IE和Firefox的Js兼容问题
- linux LVS DR模式配置
- UVA 10142 Australian Voting(模拟)
- 关于FPU
- C简单实现动态顺序表
- 【一天一道LeetCode】#84. Largest Rectangle in Histogram
- Android OpenSL ES 开发:使用 OpenSL 播放 PCM 数据
- javascript通过navigator.userAgent识别各种浏览器
- Postman接口自动化测试实例
- python_flask 基础巩固 (DEBUG模式)
- 常见的SQLALCHEMY列类型
- STS热部署,springboot项目中修改代码不用重新启动服务