第2章 Java内存区域与内存溢出异常

来源:互联网 发布:淘宝怎样取消货到付款 编辑:程序博客网 时间:2024/05/18 03:16

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 spaceat 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: 1001Exception in thread "main" java.lang.StackOverflowErrorat 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() {@Overridepublic void run() {dontStop();}});thread.start();}}public static void main(String[] args) throws Throwable{JavaVMStackOOM oom = new JavaVMStackOOM();oom.stackLeakByThread();}}

这个例子慎重,不说了,刚刚强制重启机器了

原创粉丝点击