jvm -2 虚拟栈 堆 方法区

本文探讨了Java虚拟机中栈帧的作用、栈溢出的常见原因及处理策略,以及堆内存(包括新生代的Eden和Survivor区)的定义、特点和溢出问题。还介绍了方法区的特性以及JVM内存结构的划分及其目的。
摘要由CSDN通过智能技术生成

特点

  1. 先进先出
  2. 线程运行时需要的空间
  3. 组成部分
    1. 栈帧
      1. 组成 方法的局部变量、操作数栈、动态链接、返回地址等信息
  4. 每个线程只有一个活动栈帧 对应着当前正在执行的那个方法

当一个新线程创建时,虚拟机会为其分配一块虚拟机栈内存,其大小可以在创建线程时进行指定,也可以由虚拟机在运行时动态分配。

虚拟机栈的大小由虚拟机参数 -Xss 来指定,这个参数用于设置每个线程的栈大小。例如,-Xss1m 表示每个线程的栈大小为1MB。如果不显式地指定 -Xss 参数,虚拟机会根据平台的默认值来分配栈大小。

特点

  1. 先进先出
  2. 线程运行时需要的空间
  3. 组成部分
    1. 栈帧
    2. 组成 方法的局部变量、操作数栈、动态链接、返回地址等信息
  4. 每个线程只有一个活动栈帧 对应着当前正在执行的那个方法

栈溢出

栈溢出错误通常是由于以下几种情况引起的:

  1. 递归调用深度过大: 如果一个方法在执行过程中递归调用自身,并且递归调用的深度过大,可能会导致栈帧数量过多,最终导致栈溢出错误。
  2. 方法调用链过长: 如果一个方法调用了过多其他方法,而这些方法又调用了更多的方法,形成了一个很长的方法调用链,也可能导致栈帧数量过多,最终导致栈溢出错误。
  3. 大量线程同时执行方法: 如果同时有大量的线程在执行方法调用,每个线程都会生成对应的栈帧,可能会耗尽虚拟机栈的内存空间,从而导致栈溢出错误。

为了避免栈溢出错误,可以采取以下几种措施:

  1. 减少递归调用的深度。
  2. 优化方法调用链,避免过长的方法调用链。
  3. 增加虚拟机栈的大小,可以通过虚拟机参数 -Xss 来指定虚拟机栈的大小。
  4. 减少线程的数量,避免同时有大量的线程在执行方法调用。

2.3

json 转换时候 java 对象 不能嵌套 否则 也会出现 栈溢出情况

2.5 本的方法栈

在这里插入图片描述

堆内存

定义

​ 通过new 关键字 创建对象都会使用堆内存

特点

1 线程共享的,堆内存对象需要考虑线程安全的问题

2 有垃圾回收机制

堆内存 溢出问题

 堆内存   java.lang.OutofMemoryError:Java heap space

​ 堆内存诊断

1 jps 工具

​ 查看当前系统中有哪些 java 进程

2 jmap 工具

查看堆内存占用情况 jmap -heap 进程id

3 jconsole 工具

图形界面 多功能的监测工具 可以连续监测

4 方法区

在这里插入图片描述

本地内存 - 操作系统内存 不再是 jvm内存

版本变化说明
jdk1.6及之前有永久代(permanent generation),静态变量存放在永久代上。
jdk1.7有永久代,但已经逐步”去永久代“,字符串常量池、静态变量改为保存在堆当中
jdk1.8及之后无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆当中

1.8 以前会导致 永久带 内存溢出 java.lang.OutofMemoryError:PermGen space

1.8 以后会导致 元空间内存溢出 java.lang.OutofMemoryError:Metaspace

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把 方法区描述为堆的一个逻辑部分,但是它却有一个别名叫作==“非堆”(Non-Heap)==,目的是与Java堆区 分开来。

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。多个线程同时加载统一个类时,只能有一个线程能加载该类,其他线程只能等等待该线程加载完毕,然后直接使用该类,即类只能加载一次。

  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。

  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。

  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutofMemoryError:PermGen space或者java.lang.OutOfMemoryError:Metaspace

    • 加载大量的第三方的jar包
    • Tomcat部署的工程过多(30~50个)
    • 大量动态的生成反射类
  • 关闭 JVM 就会释放这个区域的内存。

2.3

json 转换时候 java 对象 不能嵌套 否则 也会出现 栈溢出情况

堆内存

定义

​ 通过new 关键字 创建对象都会使用堆内存

特点

1 线程共享的,堆内存对象需要考虑线程安全的问题

2 有垃圾回收机制

堆内存 溢出问题

 堆内存   java.lang.OutofMemoryError:Java heap space

​ 堆内存诊断

1 jps 工具

​ 查看当前系统中有哪些 java 进程

2 jmap 工具

查看堆内存占用情况 jmap -heap 进程id

3 jconsole 工具

图形界面 多功能的监测工具 可以连续监测

本地内存 - 操作系统内存 不再是 jvm内存

版本变化说明
jdk1.6及之前有永久代(permanent generation),静态变量存放在永久代上。
jdk1.7有永久代,但已经逐步”去永久代“,字符串常量池、静态变量改为保存在堆当中
jdk1.8及之后无永久代,类型信息、字段、方法、常量保存在本地内存的元空间,但字符串常量池、静态变量仍然在堆当中

1.8 以前会导致 永久带 内存溢出 java.lang.OutofMemoryError:PermGen space

1.8 以后会导致 元空间内存溢出 java.lang.OutofMemoryError:Metaspace

在这里插入图片描述

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域,它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。虽然《Java虚拟机规范》中把 方法区描述为堆的一个逻辑部分,但是它却有一个别名叫作==“非堆”(Non-Heap)==,目的是与Java堆区 分开来。

  • 方法区(Method Area)与Java堆一样,是各个线程共享的内存区域。多个线程同时加载统一个类时,只能有一个线程能加载该类,其他线程只能等等待该线程加载完毕,然后直接使用该类,即类只能加载一次。

  • 方法区在JVM启动的时候被创建,并且它的实际的物理内存空间中和Java堆区一样都可以是不连续的。

  • 方法区的大小,跟堆空间一样,可以选择固定大小或者可扩展。

  • 方法区的大小决定了系统可以保存多少个类,如果系统定义了太多的类,导致方法区溢出,虚拟机同样会抛出内存溢出错误:java.lang.OutofMemoryError:PermGen space或者java.lang.OutOfMemoryError:Metaspace

    • 加载大量的第三方的jar包
    • Tomcat部署的工程过多(30~50个)
    • 大量动态的生成反射类
  • 关闭 JVM 就会释放这个区域的内存。

- JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和survivor。

解答 1
在新生代垃圾回收中,当对象从 Eden 区复制到 Survivor 区时,新的存活对象会被复制到两个相等大小的 Survivor 区域中的一个,通常称为 To Space。而另一个 Survivor 区域,则称为 From Space。

在一次垃圾回收之后,From Space 中的对象并不会被立即清空。相反,这个区域中的对象会被保留直到下一次垃圾回收。因为在下一次垃圾回收时,From Space 中的对象将被视为待清理的对象,并且在清理阶段被标记为垃圾,随后被清空。

所以,在新生代垃圾回收期间,只有 To Space 中的存活对象会被复制,而 From Space 中的对象不会立即被清空,而是在下一次垃圾回收中才会被清理掉。这种方式允许了在两个 Survivor 区域之间轮流进行对象复制,并保持了内存中始终有一个 Survivor 区域是空的,可以用于下一次垃圾回收。

解答2
在新生代垃圾回收中,当对象从 Eden 区复制到 Survivor 区时,新的存活对象会被复制到两个相等大小的 Survivor 区域中的一个,通常称为 To Space。而另一个 Survivor 区域,则称为 From Space。

在一次垃圾回收之后,From Space 中的对象并不会被立即清空。相反,这个区域中的对象会被保留直到下一次垃圾回收。因为在下一次垃圾回收时,From Space 中的对象将被视为待清理的对象,并且在清理阶段被标记为垃圾,随后被清空。

所以,在新生代垃圾回收期间,只有 To Space 中的存活对象会被复制,而 From Space 中的对象不会立即被清空,而是在下一次垃圾回收中才会被清理掉。这种方式允许了在两个 Survivor 区域之间轮流进行对象复制,并保持了内存中始终有一个 Survivor 区域是空的,可以用于下一次垃圾回收。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值