欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 后台管理


新闻资讯

MENU

软件开发知识
原文出处: c-rainstorm

第二章 Java 内存区域与内存溢出异常

内存区域

分派方法  <a href=苏州软件公司 略有区别" class="aligncenter size-full wp-image-30761" title="TIM截图20181208144452" src="/uploads/allimg/c181209/15442cFU640-13c7.png" />分派方法  <a href=苏州软件公司 略有区别" class="aligncenter size-full wp-image-30762" title="工具内存模子" src="/uploads/allimg/c181209/15442cFV4K0-24P3.png" />

– from 姜志明

工具建设

  1. 加载类
  2. 若已经在内存中则跳过。
  3. 类加载完今后就可以确定工具所需的空间巨细 // TODO why?
  4. 分派内存
  5. 按照 GC 接纳算法的差异,分派方法略有区别。
  6. 标志整理算法,利用空闲列表
  7. 带压缩的算法,利用指针碰撞(已分派和未分派内存间由指针脱离)
  8. 内存清零
  9. 工具初始化

工具的内存机关

  • MarkWord 占用一个 字 的巨细,个中分为两部门:
    1. 工具自身运行时元数据。譬喻,哈希码、GC 分代年数、锁状态符号等等
    2. 范例指针。指向其类的元数据。
    3. 若工具是数组则还需要生存数组的长度。
  • 域的存储顺序:
    1. 根基范例优先,长度长的优先。
    2. 父类域优先。子类较短域可插入父类域旷地。
    3. 受虚拟机分派计策参数和域界说顺序的影响。
  • 工具会见

    两种方法:

    1. 直接引用
    2. 引用句柄(句柄池)

    内存溢出异常

    常用 JVM 参数 (Java HotSpot VM)

    分派方法  <a href=苏州软件公司 略有区别" class="aligncenter size-full wp-image-30758" title="TIM截图20181208144116" src="/uploads/allimg/c181209/15442cFZ0510-491K.png" />

    常见异常及大概原因

  • 堆区
  • OutOfMemoryException。利用东西对快照举办阐明,看是否产生了内存泄露(内存中有不再利用的但无法接纳的工具或资源)。若是,昆山软件开发,则通过阐明引用链找到来源,办理问题;若不是查抄虚拟机堆参数,看是否可以或许调大。再查抄代码中是否有生命周期很长的大工具。
  • 虚拟机栈和当处所法栈
  • OutOfMemoryException。栈容量 * 线程数量 = 牢靠值。当线程数量过多时会激发,可以适当减小栈容量。
  • StackOverflowException。按异常查来源。
  • 要领区和运行时常量池
  • 直接内存溢出
  • 不正确的利用 NIO。
  • String 与字符串常量

    public class StringTest {
    	public static void main(String[] args) {
    		String m = "hello";
    		String n = "hello";
    		String u = new String(m);
    		String v = new String("hello");
    		
    		System.out.println("m == n: " + (m == n));
    		System.out.println("m == u: " + (m == u));
    		System.out.println("m == v: " + (m == v)

    分派方法  <a href=苏州软件公司 略有区别" class="aligncenter size-full wp-image-30763" title="string-const" src="/uploads/allimg/c181209/15442cFZF10-55052.png" />

    参考: 初探Java字符串

    第三章 垃圾收集器与内存分派计策

    判定工具是否存活

    1. 引用计数器算法。给工具添加一个引用计数器,增加/删除引用时对计数器举办修订。可是该要领因为无法办理轮回引用(譬喻两个工具相互引用)的问题,所以一般不利用该要领
    2. 可达性阐明算法。从 GC root 开始递归查询并标志,竣事后未被标志的(不行达的)即为可接纳的工具。GC root 共有四种:
    3. 栈中引用的工具
    4. 要领区常量引用的工具
    5. 要领区静态域引用的工具
    6. 当处所法中 JNI 引用的工具(不太懂)
    7. 接纳要领区
    8. 新生代的接纳效率可到达 70% – 95%,而永久代则低的多(性价比太低)
    9. 在大量利用反射、动态署理、CGLib 等 ByteCode 框架、动态生成 JSP 以及 OSGi 这类频繁自界说 ClassLoader 的场景都需要虚拟机有卸载类的本领。

    垃圾收集算法

    1. 标志-排除算法
    2. 扫描一遍,标志出需要接纳的工具,再扫描将其排除
    3. 标志/排除两阶段时间效率都不高,且接纳后空间较琐屑。
    4. 复制算法
    5. 将内存分为两块,当一块中内存不敷时,将个中所有存活工具复制到另一块中,接纳当前一整块。
    6. 今朝商用虚拟机多半利用这一算法接纳新生代。将内存分别为一个较大的 Eden 区和两块较小的 Survivor. Eden:Survivor = 8:1
    7. 标志整理算法
    8. 标志出须清理的工具,然后其余工具移动到一端
    9. 分代收集算法
    10. 新生代利用复制算法
    11. 永久代利用其他两种算法