这里有新鲜出炉的 Java 设计模式,程序狗速度看过来!
Java 程序设计语言
java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 程序设计语言和 Java 平台(即 JavaEE(j2ee), JavaME(j2me), JavaSE(j2se))的总称.
下面小编就为大家带来一篇浅谈 java 内存管理与内存溢出异常.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧
说到内存管理,笔者这里想先比较一下 java 与 C,C++ 之间的区别:
在 C,C++ 中,内存管理是由程序员负责的,也就是说程序员既要完成繁重的代码编写工作又要时常考虑到系统内存的维护
在 java 中,程序员无需考虑内存的控制和维护,而是交由 JVM 自动管理,这样就不容易出现内存泄漏和溢出的问题.然而,一旦出现内存泄漏和溢出方面的问题,如果不了解 JVM 的内存管理机制就很难找到错误所在.
1.JVM 运行时数据区
JVM 在运行 java 程序的时候会将它所管理的内存划分为若干个不同的区域,这些区域不仅有自己的用途,还有创建和销毁的时间.一般来说包含以下几个运行时数据区:
其中的橙色区域是各个线程私有的,即每个线程都会有自己的一份,而绿色区域是各个线程共享的.
2.java 对象的创建类加载检查
当 JVM 扫描到 new 关键字时,首先会去检查这个指令的参数是否能够在常量池中定位到一个类的符号引用,并且检查这个类的符号引用代表的类是否已被加载,解析和初始化过.如果没有,就必须先执行相应的类加载过程.
内存分配
当类加载检查通过后,JVM 需要为新生对象分配内存,即是把一块确定大小的内存从 java 堆中划分出来.常用的划分方法有两种:指针碰撞(要求堆内存绝对规整),空闲列表(堆内存并不规整).
内存初始化
JVM 需要将分配到的内存空间都初始化为零值(不包括对象头),这就保证了对象的实例字段在 java 代码中可以不赋初始值就直接使用,也就是说程序能够访问到这些字段的数据类型所对应的零值.
对象初始化
执行方法,将对象按照程序员的意愿进行初始化.
3. 对象的访问定位
对象创建好了,我们还希望能够快速的访问到这些对象,这就需要 JVM 栈上的 reference(引用)数据来找到堆中的具体对象,而目前使用最多的访问方式有 "句柄方式" 和 "直接指针" 两种.
使用句柄方式访问的话,就需要在堆中划分一部分内存来作为句柄池,reference 变量中存储的就是对象的句柄地址,而句柄中包含了对象实例数据和类型数据各自的具体地址信息.
使用直接指针访问的话,reference 变量中存储的直接就是对象地址,但是需要考虑如何放置类型数据的相关信息.
4. 内存溢出异常
JVM 运行时数据区除了 PC 寄存器之外,其他的内存区域都有可能发生内存溢出的异常情况.PC 寄存器是唯一一个在 JVM 规范中没有规定任何 OutOfMemoryError(OOM)情况的区域.
堆溢出
java 中的堆用于存储对象实例,如果不断地创建对象,并且保证 GC Roots 到对象之间有可达路径以避免 GC 的回收处理,那么在对象的数量达到最大堆的容量限制后就会发生堆溢出的异常情况.
栈溢出(包括 JVM 栈和本地方法栈)
1. 如果线程请求的栈深度大于 JVM 所允许的最大深度,将抛出 StackOverflowError 异常;
2. 如果 JVM 在扩展栈时无法申请到足够的内存空间,将抛出 OutOfMemoryError 异常.
此外,还有方法区溢出,常量池溢出,本机内存溢出等等.
以上这篇浅谈 java 内存管理与内存溢出异常就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持 PHPERZ.
来源: http://www.phperz.com/article/18/0118/352935.html