最近在看与Java相关的代码时,遇到了一些Java内存管理的问题。想起以前学习Java时,只是简单的学习了面向对象的语法,对于Java的内存管理只是简单的了解一下,此次查了一些资料,对Java的内存管理进行了学习,这篇博文主要是记录学习笔记。若后面有进一步学习JVM,则会继续更新。
如果文章中存在错误,或者描述不当,请大佬不吝赐教。 (^ - ^ )
Java中的内存有多种存在的形式,不同形式的内存有不同的功能。其中包括了Method Area, Java Stack Memory, Java Heap Memory, PC Registers, Native Stack Memory(即C Stack), 下面简单地对这些名词进行说明,更具体的说明可以参见[1][3][4]。
1, Method Area : 这一块内存区域主要用于存放编译后的代码,以及常量池,类的名字,方法等,所有的JVM Thread都共享这一块区域。
2, Java Stack Memory : Java程序执行时所使用的内存区域,每一个JVM Thread都有自己的Stack Memory。 其访问方式是FIFO,并且访问速度快于Java Heap Memory。
在调用一个方法时,首先会将参数等压入Stack Memory, 在方法执行过程中,内部的临时变量会随着时间不断地压入栈,弹出栈。
最后在方法结束时,会将返回值存放在栈中,以便其他程序能够获取返回值。
3, Java Heap Memory : 这一块区域主要是用于在程序运行的过程中,动态地为对象和类分配内存空间,这一块区域由JVM Thread共享,由于其存在竞争,故访问速度慢于Stack Memory. 并且heap memory需要GC进行回收。其主要分为以下空间:
1), Eden Space : 这一块空间用于存放新分配的对象。
2), Survivor Space : 在进行垃圾回收后,Eden Space中尚未回收的对象会被移动至这一块空间。
3), Tenured Space : 经过若干次(次数和Java Virtual Machine的实现相关)垃圾回收后,若某些对象仍然存活,则会被启动到这一块空间。
4, PC Registers : 每一个Java Thread都会有自己的PC Register, 用于记录当前Java Thread执行指令的地址。
5, Native Stack : 由于JVM底层实现时会使用一些本地的方法,这些本地方法在执行时会将信息存放在Native Stack中。
Java采用了Garbage Collector对内存空间进行管理,在对GC进一步介绍之前,先简单的介绍一下Java中各种Reference。
Java中主要包含四种Reference, 分别为Strong Reference, Week Reference, Soft Reference, Phantom Reference。关于这四种Reference的说明,详细可以参见[4]。下图是对这四种Reference的一个简单的总结。
Java中包含多种不同的GC, 垃圾回收线程的每一次启动是由Java虚拟机确定的,用户也可以执行System.gc()来启动垃圾回收线程,但是下面的假设是错误的[4] :
代码执行到System.gc()时,一定会启动垃圾回收线程。
执行System.gc()只能说明通知了Java启动一次垃圾回收,但是其启动的时间仍然由Java确定。
Java中主要包含4中GC,分别是Serial Garbage Collector, Parallel Garbage Collector, G1 Garbage Collector, Concurrent Mask Sweep(CMS) GC。其中除了Serial GC以外,其他都是采用多线程方式来实现的。关于这些不同GC的说明,详细可以参见[4][6]。
下图是对这四种Garbage Collector的一个简单的总结。
Java中使用GC管理内存,在程序执行的过程中,对于新创建的对象,其存放的内存空间为Heap Memory的Eden Space, 在一次垃圾回收的线程执行完毕后,没有被引用的对象将被回收掉,释放其所占据的内存空间。仍然被引用的对象会被移动到Survivor Space. 若某些对象在若干次垃圾回收后仍然存在,则对象被移动到Tenured Space。
本文简单的记录了Java的内存空间管理,并总结了不同形式的Object Reference和Garbage Collector。如果后面时间有时间的话,将会花费一些时间拜读一下JDK的垃圾回收机制的源代码。
[1] https://www.baeldung.com/java-stack-heap
[2] https://www.baeldung.com/jvm-parameters
[3] https://www.baeldung.com/jvm-vs-jre-vs-jdk
[4] https://dzone.com/articles/java-memory-management
[5] https://stackoverflow.com/questions/3571203/what-are-runtime-getruntime-totalmemory-and-freememory
[6] https://www.baeldung.com/jvm-garbage-collectors