JVM(一):Java内存区域与内存溢出异常 – haodro.com

您所在的位置:网站首页 jvm内存dump JVM(一):Java内存区域与内存溢出异常 – haodro.com

JVM(一):Java内存区域与内存溢出异常 – haodro.com

2023-03-20 09:37| 来源: 网络整理| 查看: 265

互联网集市收集整理的这篇技术教程文章主要介绍了JVM(一):Java内存区域与内存溢出异常,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2948字,纯文字阅读大概需要5分钟。

一.运行时数据区

  共分为5块:

程序计数器      (线程私有,当前线程所执行的字节码的行号指示器) Java虚拟机栈  (线程私有,证明周期与线程相同,描述的是Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧,用于存储:局部变量表、操作数栈、动态链接、方法出口等信息) 本地方法栈      (线程私有,本地方法栈类似于虚拟机栈,只不过执行的是Native方法) Java堆         (线程共享的一块内存区域,几乎所有的对象实例以及数组都要在堆上分配) 方法区              (线程共享,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据) 直接内存         (并不属于JVM但是需要讲一下)

    1.1  Java虚拟机栈    局部变量表: 存放了编译期可知的基本数据类型和对象引用和returnAddress类型。

  局部变量表所需的内存空间在编译期完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全正确的,在方法运行期间不会改变局部变量表的大小。

  在Java虚拟机规范中,对这个区域规定了两种异常情况:

如果线程请求的栈深度大于虚拟机所允许的栈深度,将抛出StackOverflowError异常 如果虚拟机可以动态扩展,扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

 

 1.2  Java堆

   因为几乎所有的对象实例都要分配到堆上,而GC的主要清理目标就是对象实例,所以,Java堆是GC的主要区域。

   由于现在的收集器大都采用分代收集算法,所以Java堆还可以细分:新生代和老年代;再细致一点还可以分为Eden空间,from Survivor空间 和 to Survivor空间。

   具体 回收算法和方案  稍后 详细讲解

 

 1.3 对象的创建

检查这个new  指令的参数是否能够在常量池定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有则执行类加载。 为新生对象分配内存-指针碰撞: 堆内存是规整的,则只需要移动指针获取相应大小的空间;空闲列表:堆内存不规整,需要维护一个列表记录哪些内存空间可用,从列表中获取然后分配。会产生同步问题,CAS +失败重试机制。 内存分配完成之后,给内存空间初始化为零值(不含对象头)。 设置必要信息(属于哪个类的实例,类的元数据,对象的哈希码). 虚拟机部分对象已完成,接下来按照程序构造,初始化对象

 二. OutOfMemoryError 和  StackOverflowError

    

1.java堆溢出  示例:

  配置参数:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError(dump当前内存堆的转储快照)

public class LeetCode { // 堆溢出 static class OOMobject {} public static void main(String[] args){ // 堆溢出 List 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异常。

  

以上是互联网集市为您收集整理的JVM(一):Java内存区域与内存溢出异常全部内容,希望文章能够帮你解决JVM(一):Java内存区域与内存溢出异常所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

扫描二维码推送至手机访问。

本文链接:https://www.qyyshop.com/info/968493.html



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3