总结:目录 以前的博客 课堂文章 常量池初览 字符串常量池简述 静态常量池 大整型常量池 为什么需要了解垃圾收集和内存分配 对象无效 如何判断这个引用计数算法 可达性分析算法 扩展回收方法区、垃圾回收算法、分代收集理论、标记清除标记、复制标记、排序对象排序
目录 上一篇博客:Java课堂3_初识JMM,简单理解常量池(字符串常量池、静态常量池、大整型常量池) 为什么需要了解垃圾回收和内存分配 主题死了 引用计数算法 可达性分析算法 JDK1.2及更高版本中引用的增强回收技术 垃圾收集?算法 分代收集 理论 标记 清除 标记 复制 标记 匹配 对象分配 虚拟机性能监控 故障排除工具 1. 为什么需要了解垃圾收集和内存分配
如果您需要解决各种内存溢出和内存泄漏问题,并且如果你的系统具有高并发性,如果垃圾收集成为实现这一点的瓶颈,则必须对这些“自动化”技术实施必要的监控。
监管。
2. 如何判断一个对象是否已死? 2.1. 引用计数方法为对象添加一个引用计数器。 每次引用该位置时,计数器值都会加 1。 当取消引用某个位置时,计数器值会减 1。 虽然占用额外的内存空间,但原理简单,决策效率很高。 它尚未被 Java 领域的主流虚拟机采用,因此不是一种选择。 这种看似简单的算法需要考虑许多异常,并且必须与大量附加处理相结合以确保正确的行为,例如简单的引用。 。 很难统计对象之间的交叉引用问题。 2.2.可达性分析使用GC路由的一组根对象作为起始点集。 从这些节点开始,按照引用关系向下查找。 搜索所经过的路径称为参考链。 当对象到达 GC 根时,它们之间不存在引用链,或者用图论术语来说,它们是不可到达的,证明了这一点。不再使用且可以作为 GC 根进行修改的对象包括: 虚拟机栈引用的对象(方法参数、局部变量、临时变量) 方法区静态属性引用的对象 方法区常量池引用的对象 本地方法栈 本地方法对象引用的对象。 虚拟机内部参考同步锁。 由synchronized 2.3和JDK1.2维护的对象。 引用扩展
四个新的扩展引用
强引用:传统的“引用”定义类似于Object o = new Object(),只要强引用关系仍然存在,垃圾收集器就不会重用引用对象。 软引用:描述有用,但不需要对象。 在系统遇到内存溢出异常之前,将这些对象纳入回收范围进行二次回收。 如果回收后内存仍然不足,则会抛出异常。 JDK 1.2 及更高版本提供了 SftReference 类来实现软引用。 弱引用也描述非本质对象,但其强度比弱引用弱。 弱引用引用的对象只能存活到下一次垃圾回收。 直到那件事发生。 虚拟引用:不影响对象的生存。 在每个对象上设置虚拟引用的唯一目的是当垃圾收集器回收该对象时接收系统通知。 3、回收方法区相比回收堆内存,由于回收条件恶劣,方法区区域垃圾回收的结果往往很低。 方法区的垃圾收集主要包括两部分: 废弃的常量:字符串 常量池中未使用的常量等类型:类、接口、方法、字段 符号引用等。 要确定某个类何时不再存在,必须考虑该类的所有实例都已被回收。 加载该类的类加载器已被回收。 java.lang.Class 对象没有在任何地方被引用,也不能通过反射访问该类的方法。 使用大量反射、动态代理、CGLIB 和其他字节码的框架动态生成频繁定制的类,例如 JSP。 加载器场景通常要求 Java 虚拟机具有卸载类型的能力,以避免对方法区造成过大的内存压力。 4. 垃圾收集算法
垃圾收集算法可以分类如下
引用计数垃圾收集(对应之前的引用计数算法) 跟踪类型垃圾收集(使用之前的可达性分析算法)
分代收集设计原则
弱分代假设:对象被创建和销毁。 强生成假设:对象在垃圾回收中幸存的次数越多,保存它就越困难。
那就是
有partial GC、young GC、old GC、mixed GC、full heap collection、full GC 4.1。 标记和清除算法
该算法分为两个阶段:标记和清除
标记:首先标记所有要回收的对象(或存活对象),标记完成后将其清除。 所有标记的对象将被一起删除。 回收
缺点
执行效率不是很好。 稳定性:如果Java堆中包含大量对象,其中大部分需要回收,则需要进行大量的标记和清除操作。 内存空间碎片问题:清理后会产生大量不连续的内存空间。 如果您需要分配一个大对象,那么是的,这可能还不够,并且需要 GC。 4.2. 标记复制算法
与标记清除算法比较
半区复制:将内存容量分成大小相等的两个块,一次只使用一个块。 当该内存耗尽时,幸存的对象将被复制到另一部分,并且所有已使用的内存将被回收并清理。 缺点:该算法产生大量的内存区域复制开销,使可用内存减少到原来大小的一半,浪费空间。
半区复制生成策略
Appel式回收:新生代虚拟机使用这种回收算法,将新生代按照8:1:1的比例分割成Eden区和Survivor区。 每次Eden运行时,都需要上一代的内存保证,才能将幸存的对象放入Survivor中。 这意味着Survivor必须将对象转移到上一代。 4.3. 标记排序算法
与新一代使用的标记复制算法和标记清除算法相比不能使用。 浪费内存空间。 针对老年代对象的死亡率特性需要使用mark-排序算法。 与mark-清除算法的本质区别在于,它不是直接清理可回收对象,而是将幸存的对象移动到区域中以清除边界外的内存。
函数
移动当移动活动对象时,尤其是在老一代中,所有用户程序都必须停止世界来移动对象地址。 当世界不动时,使用标记和清晰的算法。 当内存分配很复杂时,移动过程中会使用标记排序算法。 如果您的回收更加复杂,可以选择以下一些选项: 在Mud方法中,当破碎程度达到一定程度时,它就开始迁移。 5. 对象分配
从概念上讲,对象的内存分配是在堆上分配的。 (实际上,即时编译后,可能会在栈上间接拆解为标量类型(分配)。在经典的分代设计中,新对象直接分配到新生代,有些大对象会超过它。 阈值可以直接分配在老一代中。
该对象首先被分配给Eden。 幸存者对象因为没有足够的空间来触发YoungGC而进入Survivor。 大对象直接进入老年代。 为了避免大对象内存复制的开销,大对象直接分配到老年代。 设置 -XX:PretenureSizeThreshold=3145728 参数来指定阈值会导致长寿命对象进入老年代。 :虚拟机为每个对象定义一个对象年龄(Age)计数器,并将其存储在对象头中。 对象通常包含在 Eden 列表中。 如果第一个管理器 YongGC 幸存并能够释放幸存者,则该对象将移动到幸存者并为其年龄增加 1 年。 一旦年龄达到一定级别(默认为15岁),就会被放入时代名称中。 动态对象老化可以通过-XXMaxTenuringThreshold设置。 除了对象的年龄增加而进入老年代之外,如果Survivor空间中相同年龄的对象总数大于Survivor空间的一半,那么该对象将无法直接进入老年代。 空间分配保证:当YoungGC发生时,虚拟机首先要检查老年代中最大可用连续空间是否大于新生代中所有对象的空间总和。 如果这个条件为真,则保证这次GC是安全的。 如果此条件不成立,虚拟机将检查 -XX:HandlePromotionFailure 参数是否允许保证失败。 如果允许,则检查老年代的可用连续空间是否大于老年代对象的平均大小。 如果很大,则继续。如果 YoungGC 小于 YoungGC 的值或者 -XX:handlePromotionFailure 设置不接受风险,则需要 FullGC。 6. 虚拟机性能监控故障排除工具 6.1 基本故障排除工具
jsp:虚拟机进程状态工具 虚拟机进程显示和搜索工具
jstat:虚拟机统计监控工具,显示类等运行时数据加载、内存、垃圾收集器和即时编译。 识别虚拟机性能问题的参数参考:https://blog.csdn.net/ouyang111222/article/details/53688986
jinfo:Java配置信息工具
jmap:镜像工具用于生成Java内存堆转储快照
jhat:虚拟机堆转储快照分析工具
jstack:Java堆栈跟踪工具
jcmd:虚拟机诊断命令Java7以来提供的工具
Java基础工具
javadoc:API文档生成器 javap:字节码分析工具 6.2可视化排错工具 jhsdb:Java 9以来提供的进程调试器,基于服务代理的调试工具,首先用于查看 jps 中的进程号,然后用于查看 jhsdb hsdb --pid xxx 要使用 JConsole:Java 监控和管理控制台 在控制台中键入 jconsole 以进行本地和远程连接。 VisualVM:多禾-故障排除工具
评论前必须登录!
注册