Java的内存区域与内存溢出异常你了解吗
1. 运行时数据区域

1. 程序计数器(线程私有)
当前线程所执行的字节码的行号指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都要考程序计数器。(记住程序当前走到的位置,下次还回来)。线程私有。
2. Java虚拟机栈(线程私有)
和方法相关联,每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程
线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常(常见的递归层数过多导致”爆栈“)
3. 本地方法栈(线程私有)
类似于Java虚拟机栈。区别在于:
虚拟机栈为虚拟机执行Java方法本地方法栈则为虚拟机使用到的Native方法服务
Java开头通过Java Native Interface来调用本地方法(一般用C语言编写)
4. Java堆(线程共享)
Java虚拟机所管理的内存中最大的一块new出来的对象就存在于堆上垃圾收集器管理的主要区域
5. 方法区(线程共享)
存储已被虚拟机加载的类信息、常量、静态变量
6. 运行时常量池
方法区的一部分用于存放编译期生成的各种字面量和符号引用
2. 对象是如何创建的?
Object obj=new Object(): 分析这行代码的执行过程
使用了new关键字,检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。没有的话先加载类类加载检查通过后,虚拟机将为新生对象分配内存内存分配完成后,虚拟机需要将分配到的内存空间都初始化为零值虚拟机要对对象进行必要的设置,例如将对象的哈希码、元数据、GC分代年龄、是否使用偏向锁等数据存放在对象头中执行init方法,把对象按照程序员的意愿进行初始化(给成员变量赋的值)
3. 对象的内存布局


4. 对象的访问定位
1. 句柄访问
Java堆中将会划分出一块内存来作为句柄池,reference中存储的就是对象的句柄地址,而句柄中包含了对象实例数据与类型数据各自的具体地址信息

2. 直接指针访问
Java堆对象的布局中就必须考虑如何放置访问类型数据的相关信息,而reference中存储的直接就是对象地址

二者比较:
使用句柄来访问的最大好处就是reference中存储的是稳定的句柄地址,即使对象被移动(GC过程),只需要改变句柄中的示例指针,无需变动refrence直接指针访问方式的最大好处就是速度更快, refrence直接指向实例数据,减少了一次指针访问
HotSpot虚拟机使用直接指针方式进行对象访问的
5. OutOfMemoryError异常代码演示
1. Java堆溢出
package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
static class MyObject{
}
public static void main(String[] args) {
List<MyObject> list=new ArrayList<>();
int i=0;
while(true)
{
System.out.println(i++);
list.add(new MyObject());
}
}
}


限制Java堆的大小为20MB,不可扩展(将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数-XX:+HeapDumpOnOutOfMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析
2. 虚拟机栈溢出
如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常
package jvm;
import java.util.ArrayList;
import java.util.List;
public class OutOfMemoryErrorDemo {
static int i=0;
public static void main(String[] args) {
f();
}
public static void f() {
System.out.println(i++);
f();
}
}


相同的Xss(线程的堆栈大小)下,如果栈中的本地数据较多,那么相应的可以递归的次数就越少
还有1种栈溢出会报OutOfMemoryError异常,如果虚拟机在扩展栈时无法申请到足够的内存空间,则抛出OutOfMemoryError异常,比如将上面的递归改成多线程版就会出现这种问题
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
相关文章
利用MyBatis-Plus灵活处理JSON字段的技巧与最佳实践
这篇文章主要给大家介绍了关于利用MyBatis-Plus灵活处理JSON字段的技巧与最佳实践,Mybatis-Plus可以很方便地处理JSON字段,在实体类中可以使用@JSONField注解来标记JSON字段,需要的朋友可以参考下2024-07-07
idea打开项目后无法显示目录结构,只能显示.iml文件问题
这篇文章主要介绍了idea打开项目后无法显示目录结构,只能显示.iml文件问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-08-08
Springboot内置的工具类之CollectionUtils示例讲解
这篇文章主要介绍了Springboot内置的工具类之CollectionUtils,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-12-12
Java8新特性之泛型的目标类型推断_动力节点Java学院整理
泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。下面通过本文给分享Java8新特性之泛型的目标类型推断,感兴趣的朋友参考下吧2017-06-06
spring cloud中微服务之间的调用以及eureka的自我保护机制详解
这篇文章主要介绍了spring cloud中微服务之间的调用以及eureka的自我保护机制详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-07-07
SpringBoot注解@ConditionalOnClass底层源码实现
这篇文章主要为大家介绍了SpringBoot注解@ConditionalOnClass底层源码实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪2023-02-02
SpringBoot集成elasticsearch使用图文详解
Spring Boot集成Elasticsearch其实非常简单,这篇文章主要给大家介绍了关于SpringBoot集成elasticsearch使用的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下2023-04-04


最新评论