1、运行时数据区域
1.1 程序计数器
通俗讲就是工作开展什么位置了,每个线程都一个单独程序计数器,线程执行java方法,计数器指向字节码指令地址,执行native方法,计数器为空,它也是唯一没有规定OutOfMemoryError情况。
1.2 java虚拟机栈
执行方法会创建栈帧(Stack Frame) ,保存局部变量、操作栈、动态链接、方法出口,(可以这么认为,当前做的事情需要什么原料,什么工具,接下应该做啥)
局部变量表存放基本数据类型和引用变量,它所需要的内存空间在编译器间完成分配。
StackOverflowError异常:从java虚拟机栈的深度超过的允许的深度(从纵向来说) 修改栈深度将会抛出
OutOfMemoryError异常:栈扩展的无法分配到足够的内存时抛出(从横向来说) 多线程抛出
1.3 本地方法栈(Native Method Stacks)
它与java虚拟机栈类似,只不过本地方法栈为虚拟机使用到的Native方法服务,而java虚拟机栈为字节码服务
1.4 java 堆
堆存具体的数据和实例,分配内存可以物理上不连续,必须逻辑上是连续的
1.5. 方法区
各个线程共享的内存区域,包括编译的代码,类的信息、常量、静态变量
1.6 运行时常量池
它是方法区一部分,存放编译器生成的各种字面量和符号引用
1.7 直接内存
它不是虚拟机运行时数据区的一部分,也不是虚拟机规范中定义的内存,但是它经常被使用。
1.8对象访问
有两种:1、句柄,修改方便
2、指针 执行速度快
2、实战
2.1 OutOfMemoryError异常
2.1.1 java 堆溢出
package contacts;
import java.util.ArrayList;
import java.util.List;
/**
* VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
* @author Administrator
*
*/
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while(true) {
list.add(new OOMObject());
}
}
}
-verbose:gc -Xms20m -Xmx20m -Xmn10m -XX:+PrintGCDetails -XX:SurvivorRatio=8日志:
[GC (Allocation Failure) [PSYoungGen: 7693K->1000K(9216K)] 7693K->5321K(19456K), 0.0567310 secs] [Times: user=0.06 sys=0.00, real=0.06 secs]
[GC (Allocation Failure) --[PSYoungGen: 9192K->9192K(9216K)] 13513K->19424K(19456K), 0.0221517 secs] [Times: user=0.06 sys=0.00, real=0.02 secs]
[Full GC (Ergonomics) [PSYoungGen: 9192K->0K(9216K)] [ParOldGen: 10232K->10122K(10240K)] 19424K->10122K(19456K), [Metaspace: 2664K->2664K(1056768K)], 0.1533004 secs] [Times: user=0.30 sys=0.00, real=0.15 secs]
[Full GC (Ergonomics) [PSYoungGen: 7527K->7912K(9216K)] [ParOldGen: 10122K->8012K(10240K)] 17650K->15925K(19456K), [Metaspace: 2664K->2664K(1056768K)], 0.1317532 secs] [Times: user=0.25 sys=0.02, real=0.13 secs]
[Full GC (Allocation Failure) [PSYoungGen: 7912K->7912K(9216K)] [ParOldGen: 8012K->8012K(10240K)] 15925K->15924K(19456K), [Metaspace: 2664K->2664K(1056768K)], 0.0730385 secs] [Times: user=0.19 sys=0.00, real=0.07 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:261)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
at java.util.ArrayList.add(ArrayList.java:458)
at contacts.HeapOOM.main(HeapOOM.java:18)
Heap
PSYoungGen total 9216K, used 8192K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 100% used [0x00000000ff600000,0x00000000ffe00000,0x00000000ffe00000)
from space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
to space 1024K, 47% used [0x00000000fff00000,0x00000000fff790e0,0x0000000100000000)
ParOldGen total 10240K, used 8012K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 78% used [0x00000000fec00000,0x00000000ff3d3068,0x00000000ff600000)
Metaspace used 2696K, capacity 4486K, committed 4864K, reserved 1056768K
class space used 289K, capacity 386K, committed 512K, reserved 1048576K
2.1.2 虚拟机栈和本地方法栈溢出
抛出StackOverflowError
修改-Xss参数减少栈的内存容器
package contacts;
/**
* VM Args: -Xss128k
* @author Administrator
*
*/
public class JavaVMStackSOF {
private int stackLength =1;
public void stackLeak() {
stackLength++;
stackLeak();
}
public static void main(String[] args) {
JavaVMStackSOF oom = new JavaVMStackSOF();
try {
oom.stackLeak();
} catch (Throwable e) {
System.out.println("stack length: " + oom.stackLength);
throw e;
}
}
}
日志:
stack length: 1001
Exception in thread "main" java.lang.StackOverflowError
at contacts.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:10)
at contacts.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:11)
这个长度不是固定,随着变化,但变化不大抛出OutOfMemoryError
package contacts;
/** VM Args: -Xss2M
*/
public class JavaVMStackOOM {
private void dontStop(){
while(true) {
}
}
public void stackLeakByThread() {
while(true) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) throws Throwable{
JavaVMStackOOM oom = new JavaVMStackOOM();
oom.stackLeakByThread();
}
}
这个例子慎重,不说了,刚刚强制重启机器了