目录
1.首先一个main线程会执行main()方法里的代码,main线程自己是有一个Java虚拟机栈的,他会把main()方法的栈帧压入Java虚拟机栈。
4.接下来就会执行通过局部变量“replicaManager”引用的实例对象“ReplicaManager”去执行他的load()方法,去完成我们实现的业务逻辑。
一、对象的分配与引用
结合我们之前理解过的JVM运行原理,让我们来拆解下面代码的运行流程把!
public class Demo {
public static void main(String[] args) {
loadReplica();
}
public static void loadReplica() {
ReplicaManager replicaManager = new ReplicaManager();
replicaManager.load();
}
}
1.首先一个main线程会执行main()方法里的代码,main线程自己是有一个Java虚拟机栈的,他会把main()方法的栈帧压入Java虚拟机栈。
2.接着main()方法里调用了loadReplica()方法那么就会创建loadReplica()方法的栈帧,压入main线程的Java虚拟机栈里去,此时发现在loadReplica()方法里,有一个“replicaManager ”变量,那么就会在loadReplica()方法对应的栈帧里,放入一个“repliaManager”变量。
3.接着代码里创建了一个“ReplicaManager”类的实例对象,此时就会在Java堆内存中分配这个实例对象的内存空间。同时,让loadReplica()方法的栈帧内的“replicaManager”局部变量去指向那个Java堆内存里的ReplicaManager实例对象
4.接下来就会执行通过局部变量“replicaManager”引用的实例对象“ReplicaManager”去执行他的load()方法,去完成我们实现的业务逻辑。
5.一旦你的loadReplica()方法执行完毕,此时就会把loadReplica()方法对应的栈帧从main线程的Java虚拟机栈里出栈,这个时候没有任何一个变量指向Java堆内存里的“ReplicaManager”实例对象
6.核心点来了,我们启动的Java系统本质就是一个JVM进程,他负责运行我们的系统的代码,这个JVM进程本身也是会占用机器上的部分内存资源,所以我们在Java堆内存里创建的对象,都是占用内存资源的,而且内存资源有限。
这种不需要使用却还占着内存资源的情况该怎样处理呢?
答:JVM的垃圾回收机制。
这是一个后台自动运行的线程,只要启动一个JVM进程,他就会自带一个垃圾回收的后台线程。
这个线程会在后台不断检查JVM堆内存中的各个实例对象,这些不再被指向的对象实例,即JVM中的“垃圾”,就会定期的被后台垃圾回收线程清理掉,不断释放内存资源。
二、JVM分代模型
在 Java 中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。
1.新生代
新生代一般分三个区:一个Eden区,两个Survivor区,正常对象生成在Eden区。当Eden区满时,还存活的对象将被复制到两个Survivor区(中的一个)。当这个Survivor区满时,又将被复制到另外一个Survivor区。对象经历多次Minor GC后会被放到老年代。
2.老年代(Old Generation)
在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代。老年代的垃圾回收(又称Major GC)通常使用“标记-清理”或“标记-整理”算法。
3.永久代(Perm Generation)
Java7及以前版本的Hotspot中方法区位于永久代中,在Java8中,Hotspot取消了永久代,永久代的参数-XX:PermSize和-XX:MaxPermSize也随之失效。
在Java8中方法区存在于元空间(Metaspace)。