JVM内存结构
每起一个线程,都会在栈内存中开辟一块专属于该线程的空间,该线程每调用一个方法就会启动一个栈帧
方法区在JDK8中改名叫永久区,存放Class文件,静态变量,常量,常量池等。
堆内存
大小比例: eden:s1:s2 = 8:1:1 ,new:old = 1:3 或者 3: 8
这些比例可以配置的
- 新创建(new)的对象如果特别大,则直接放入老年代区(tenured),否则放入eden区
- 当进行gc时,将eden区和s1中的垃圾清理后,将s1整个复制到s2中,eden区存活的对象也复制到s2;下次gc时进行清理后,将s2整个复制到s1,并且eden区存活的对象复制到s2,如此反复
- 若有对象一直在s1和s2中反复移动,到达一定次数后,则从新生代移动到老年代
对象的分配
对象分配的过程:
- 创建对象时,若对象很小,则直接在分配在线程的栈空间的栈帧中(方法调用),好处是当方法结束或线程结束,则对象的内存可直接回收,不需要垃圾收集器进行回收
- 若线程栈帧中分配不下,则会在线程本地缓存分配,即TLAB
- 若线程本地缓存放不下,且对象特别大,则放入老年代,否则放入eden区
垃圾
Java采用正向可达的算法
新生代采用复制算法:存活对象少,效率高
老年代采用标记压缩算法:
- 每次gc时产生的垃圾比较少
- 标记压缩后,保证没有内存碎片,可以存放大对象
JVM参数
垃圾收集器
- Serial Collector 一般不用
- Parallel Collector JDK8默认的收集器,多处理器并行进行垃圾回收,但是停顿时间长,可能会达到1秒或更长, -XX:+UseParallelGC
- CMS Collector 采用并发进行垃圾回收,响应快,停顿时间短,-XX:UseConMarkSweepGC
- G1 采用并发进行垃圾回收,响应快,不仅停顿时间短,并发大,停顿时间比CMS略长,-XX:UseG1GC