浅谈java内存管理与内存溢出异常

所属分类: 软件编程 / java 阅读数: 22
收藏 0 赞 0 分享

说到内存管理,笔者这里想先比较一下java与C、C++之间的区别:

在C、C++中,内存管理是由程序员负责的,也就是说程序员既要完成繁重的代码编写工作又要时常考虑到系统内存的维护

在java中,程序员无需考虑内存的控制和维护,而是交由JVM自动管理,这样就不容易出现内存泄漏和溢出的问题。然而,一旦出现内存泄漏和溢出方面的问题,如果不了解JVM的内存管理机制就很难找到错误所在。

1.JVM运行时数据区

JVM在运行java程序的时候会将它所管理的内存划分为若干个不同的区域,这些区域不仅有自己的用途,还有创建和销毁的时间。一般来说包含以下几个运行时数据区:

其中的橙色区域是各个线程私有的,即每个线程都会有自己的一份,而绿色区域是各个线程共享的。

2.java对象的创建

类加载检查

当JVM扫描到new关键字时,首先会去检查这个指令的参数是否能够在常量池中定位到一个类的符号引用,并且检查这个类的符号引用代表的类是否已被加载、解析和初始化过。如果没有,就必须先执行相应的类加载过程。

内存分配

当类加载检查通过后,JVM需要为新生对象分配内存,即是把一块确定大小的内存从java堆中划分出来。常用的划分方法有两种:指针碰撞(要求堆内存绝对规整)、空闲列表(堆内存并不规整)。

内存初始化

JVM需要将分配到的内存空间都初始化为零值(不包括对象头),这就保证了对象的实例字段在java代码中可以不赋初始值就直接使用,也就是说程序能够访问到这些字段的数据类型所对应的零值。

对象初始化

执行<init>方法,将对象按照程序员的意愿进行初始化。

3.对象的访问定位

对象创建好了,我们还希望能够快速的访问到这些对象,这就需要JVM栈上的reference(引用)数据来找到堆中的具体对象,而目前使用最多的访问方式有“句柄方式”和“直接指针”两种。

使用句柄方式访问的话,就需要在堆中划分一部分内存来作为句柄池,reference变量中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息。

使用直接指针访问的话,reference变量中存储的直接就是对象地址,但是需要考虑如何放置类型数据的相关信息。

4.内存溢出异常

JVM运行时数据区除了PC寄存器之外,其他的内存区域都有可能发生内存溢出的异常情况。PC寄存器是唯一一个在JVM规范中没有规定任何OutOfMemoryError(OOM)情况的区域

堆溢出

java中的堆用于存储对象实例,如果不断地创建对象,并且保证GC Roots到对象之间有可达路径以避免GC的回收处理,那么在对象的数量达到最大堆的容量限制后就会发生堆溢出的异常情况。

栈溢出(包括JVM栈和本地方法栈)

1.如果线程请求的栈深度大于JVM所允许的最大深度,将抛出StackOverflowError异常;

2.如果JVM在扩展栈时无法申请到足够的内存空间,将抛出OutOfMemoryError异常。

此外,还有方法区溢出、常量池溢出、本机内存溢出等等。

以上这篇浅谈java内存管理与内存溢出异常就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

Java的面向对象编程基本概念学习笔记整理

这篇文章主要介绍了Java的面向对象编程基本概念学习笔记整理,包括类与方法以及多态等支持面向对象语言中的重要特点,需要的朋友可以参考下
收藏 0 赞 0 分享

Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法

这篇文章主要介绍了Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

基于Java实现杨辉三角 LeetCode Pascal's Triangle

这篇文章主要介绍了基于Java实现杨辉三角 LeetCode Pascal's Triangle的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中Spring获取bean方法小结

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?下面通过本文给大家介绍Java中Spring获取bean方法小结,对spring获取bean方法相关知识感兴趣的朋友一起学习吧
收藏 0 赞 0 分享

如何计算Java对象占用了多少空间?

在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小,需要的朋友可以参考下
收藏 0 赞 0 分享

剖析Java中的事件处理与异常处理机制

这篇文章主要介绍了Java中的事件处理与异常处理机制,讲解Java是如何对事件或者异常作出响应以及定义异常的一些方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Java的Struts2框架的结构及其数据转移方式

这篇文章主要介绍了详解Java的Struts2框架的结构及其数据转移方式,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

Java封装好的mail包发送电子邮件的类

本文给大家分享了2个java封装好的mail包发送电子邮件的类,并附上使用方法,小伙伴们可以根据自己的需求自由选择。
收藏 0 赞 0 分享

在Java的Struts中判断是否调用AJAX及用拦截器对其优化

这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

java多线程Future和Callable类示例分享

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。今天我们就来研究下Future和Callab
收藏 0 赞 0 分享
查看更多