Java和c c++不同,c c++都是直接经过手动的方式来申请内存,释放内容。而java拥有良好的内存自动管理机制。因此在咱们开发java程序代码的时候,通常状况下不须要关心java的内存问题。java
Java的内存区域图:c++
上面的图就是Java运行时的内存数据区域。分红方法区,虚拟机栈,本地方法栈,堆,程序计数器。数组
做用:程序计数器是一块很小的内存空间,主要是线程所执行的字节码的行号指示器。每一个线程都会有独立的程序计数器。工具
Java的虚拟机栈也是线程私有的,生命周期和线程相同。虚拟机栈描述的是Java方法执行的内存模型:每一个方法被执行的时候都会同时建立一个栈帧(Stack Frame)用于存储局部变量表、操做数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完成的过程,就是对应着一个栈帧在VM Stack中从入栈到出栈的过程。spa
本地方法栈主要为虚拟机使用的Native方法服务,也是栈的一部分。线程
虚拟机栈会抛两种异常:code
1. StackOverflowError异常。一般主要是线程请求的栈深度大于虚拟机所容许的深度。好比递归层次太深就有可能致使这个异常出现,通常1000-2000层之间。减小递归层次能够减少这个防范。也能够经过参数-Xss128k 能够设置每一个线程的栈大小。对象
2. OutOfMemoryError异常。主要是内存不够。递归
Java内存中最大的块就是堆。全部的对象实例和数组都会分配在java的堆上面。Java堆也是内存GC的重要区域。生命周期
Java堆异常:
1. OutOfMemoryError异常。Java堆内存溢出能够经过设置参数-Xmx3550m -Xms3550m来控制堆内存的大小。-Xms是最小值,-Xmx是最大值。
通常堆溢出:java.lang.OutOfMemoryError: Java heap space
异常提示中都有Java heap space 说明是堆溢出。
通常解决堆溢出思路有三种:
1. 经过内存影像分析工具(Eclipse Memory Analyzer)来定位堆溢出问题
2. 分析是否有内存泄露
3. 调整堆参数。
方法区也是各线程共享的内存区域,主要存放虚拟机加载的类信息、常量、静态变量等信息。
运行时常量池也是方法区的一部分,做用是存储编译期生成的各类字面量和符号引用。
1. OutOfMemoryError异常。发生异常时,主要抛下面相似的异常信息:
Exception in thread "main" java.lang.OutOfMemoryError: PermGen space at java.lang.String.intern(Native Method) at org.fenixsoft.oom.RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:18)
能够看到有 PermGen space的提示则表示方法区溢出。
方法区溢出,能够经过限制方法区的内存大小来限制:-XX:PermSize 和 -XX:MaxPermSize
Java1.7的PermGen默认空间为85 MB(或者能够经过-XX:MaxPermSize=XXXm指定)
须要注意的是,PermGen space是Oracle-Sun Hotspot才有,JRockit以及J9是没有这个区域。