深入理解Java虚拟机(二)——对象访问

时间:2022-02-21 10:14:48

创建一个对象
Object obj = new Object();

在这句代码中Object obj是一个对象的引用,作为一个reference类型存放在本地变量表(Java虚拟机栈)中,而new Object()则反映在Java堆中,形成一块存储了Object类型所有实例数据值的结构化内存,同时Java堆还包含能够查找到此对象类型数据(如对象类型,父类,实现的接口,方法)的地址,而方法区就存储了这些对象类型数据

这个对象引用可以通过两种方式去定位,去访问对象:
1. 使用句柄: Java堆中划出一块内存作为句柄池,所以reference类型保存的就是句柄地址,而句柄值保存对象实例数据(Java堆实例池)和类型数据(方法区)的地址
2. 使用指针(HotSpot使用该种方式): reference类型直接保存对象地址,指向Java堆中的对象,再有该对象中的指针指向方法区的对象类型数据

使用句柄访问方式的优点是对象移动时reference类型不必修改,而指针访问方式的优点是节省了一次指针定位的开销

实战练习

Java堆溢出:(不断创建对象,保证GC Roots到对象之间有可达路径避免垃圾回收机制清楚这些对象???,就会在对象数量到达最大堆容量限制后产生内存溢出异常 OnOutOfMemoryError)
首先设置虚拟机的堆大小限制(Idea中设置VM options),参数为
-verbose:gc
-Xms20M 最小值
-Xmx20M 最大值 两个值都是20m避免Java堆自动拓展
-Xmn10M
-XX:+PrintGCDetails
-XX:SurvivorRatio=8

测试程序:

package com.zxc.memoryError;

import java.util.ArrayList;
import java.util.List;

public class memoryError {
static class OOMObject{
public static void main(String[] args){
List<OOMObject> list=new ArrayList<>();

while(true){
list.add(new OOMObject());
}
}
}
}

控制台抛出异常

/opt/jdk1.8.0_152/bin/java -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -javaagent:/opt/idea/lib/idea_rt.jar=36611:/opt/idea/bin -Dfile.encoding=UTF-8 -classpath /opt/jdk1.8.0_152/jre/lib/charsets.jar:/opt/jdk1.8.0_152/jre/lib/deploy.jar:/opt/jdk1.8.0_152/jre/lib/ext/cldrdata.jar:/opt/jdk1.8.0_152/jre/lib/ext/dnsns.jar:/opt/jdk1.8.0_152/jre/lib/ext/jaccess.jar:/opt/jdk1.8.0_152/jre/lib/ext/jfxrt.jar:/opt/jdk1.8.0_152/jre/lib/ext/localedata.jar:/opt/jdk1.8.0_152/jre/lib/ext/nashorn.jar:/opt/jdk1.8.0_152/jre/lib/ext/sunec.jar:/opt/jdk1.8.0_152/jre/lib/ext/sunjce_provider.jar:/opt/jdk1.8.0_152/jre/lib/ext/sunpkcs11.jar:/opt/jdk1.8.0_152/jre/lib/ext/zipfs.jar:/opt/jdk1.8.0_152/jre/lib/javaws.jar:/opt/jdk1.8.0_152/jre/lib/jce.jar:/opt/jdk1.8.0_152/jre/lib/jfr.jar:/opt/jdk1.8.0_152/jre/lib/jfxswt.jar:/opt/jdk1.8.0_152/jre/lib/jsse.jar:/opt/jdk1.8.0_152/jre/lib/management-agent.jar:/opt/jdk1.8.0_152/jre/lib/plugin.jar:/opt/jdk1.8.0_152/jre/lib/resources.jar:/opt/jdk1.8.0_152/jre/lib/rt.jar:/home/russell/IdeaProjects/java_test/out/production/java_test:/home/russell/IdeaProjects/java_test/lib/mysql-connector-java-5.1.45-bin.jar com.zxc.memoryError.memoryError$OOMObject
[GC (Allocation Failure) [PSYoungGen: 8192K->1017K(9216K)] 8192K->4921K(19456K), 0.0327340 secs] [Times: user=0.02 sys=0.01, real=0.04 secs]
[GC (Allocation Failure) [PSYoungGen: 9209K->1024K(9216K)] 13113K->10742K(19456K), 0.0335066 secs] [Times: user=0.04 sys=0.00, real=0.04 secs]
[Full GC (Ergonomics) [PSYoungGen: 1024K->511K(9216K)] [ParOldGen: 9718K->10175K(10240K)] 10742K->10687K(19456K), [Metaspace: 3268K->3268K(1056768K)], 0.2420921 secs] [Times: user=0.34 sys=0.00, real=0.24 secs]
[Full GC (Ergonomics) [PSYoungGen: 8358K->8232K(9216K)] [ParOldGen: 10175K->8058K(10240K)] 18533K->16291K(19456K), [Metaspace: 3268K->3268K(1056768K)], 0.1626348 secs] [Times: user=0.37 sys=0.00, real=0.16 secs]
[Full GC (Allocation Failure) 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:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at com.zxc.memoryError.memoryError$OOMObject.main(memoryError.java:12)
[PSYoungGen: 8232K->8232K(9216K)] [ParOldGen: 8058K->8040K(10240K)] 16291K->16273K(19456K), [Metaspace: 3268K->3268K(1056768K)], 0.1633865 secs] [Times: user=0.34 sys=0.00, real=0.17 secs]
Heap
PSYoungGen total 9216K, used 8640K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
eden space 8192K, 99% used [0x00000000ff600000,0x00000000ffdf0180,0x00000000ffe00000)
from space 1024K, 49% used [0x00000000fff00000,0x00000000fff7ff00,0x0000000100000000)
to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000)
ParOldGen total 10240K, used 8040K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
object space 10240K, 78% used [0x00000000fec00000,0x00000000ff3da258,0x00000000ff600000)
Metaspace used 3300K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 361K, capacity 388K, committed 512K, reserved 1048576K

Process finished with exit code 1

具体处理Java堆内存问题会在后面几章提到