标签:对象 容量 算法 就会 无法 内存泄露 int 收集 内存分配
一.运行时数据区
共分为5块:
1.1 Java虚拟机栈
局部变量表: 存放了编译期可知的基本数据类型和对象引用和returnAddress类型。
局部变量表所需的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全正确的,在方法运行期间不会改变局部变量表的大小。
在Java虚拟机规范中,对这个区域规定了两种异常情况:
1.2 Java堆
因为几乎所有的对象实例都要分配到堆上,而GC的主要清理目标就是对象实例,所以,Java堆是GC的主要区域。
由于现在的收集器大都采用分代收集算法,所以Java堆还可以细分:新生代和老年代;再细致一点还可以分为Eden空间,from Survivor空间 和 to Survivor空间。
具体 回收算法和方案 稍后 详细讲解
1.3 对象的创建
二. OutOfMemoryError 和 StackOverflowError
1.java堆溢出 示例:
配置参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError(dump当前内存堆的转储快照)
public class LeetCode { // 堆溢出 static class OOMobject {} public static void main(String[] args){ // 堆溢出 List<OOMobject> list = new ArrayList<>(); while(true){ list.add(new OOMobject()); } } }
使用Jhat查看解析快照文件。
解决方案:1.查看是否是内存泄露,可以用工具查看GC Roots与对象的关联路径 判断哪些对象是无用的,什么原因导致GC无法回收
2.如不存在泄露,应当查看 堆参数 也就是 -Xmx 和 -Xms,看一下物理内存是否还允许堆内存调大一些
3.从代码上检查是否存在某些对象的生命周期过长、持有状态时间过长的情况,尝试优化代码减少内存消耗。
2.虚拟机栈溢出
public class LeetCode { private int stackLength = 1; public static void main(String[] args) throws Throwable{ LeetCode leetCode = new LeetCode(); try{ leetCode.stackLeak(); } catch (Throwable e) { System.out.println("stack length:" + leetCode.stackLength); throw e; } }
public void stackLeak() {
stackLength++;
stackLeak();
}
}
使用 -Xss参数,减小栈的内存容量。结果抛出StackOverFlowError异常。
标签:对象 容量 算法 就会 无法 内存泄露 int 收集 内存分配
原文地址:https://www.cnblogs.com/maxm/p/10966456.html