Java 内存分配和垃圾
2016-05-12 本文已影响38人
鬼谷神奇
在JDK7中,有5种垃圾收集器:
Serial收集器
Parallel收集器
Parallel Old收集器 (Parallel Compacting GC)收集器
Concurrent Mark & Sweep GC (or “CMS”)收集器
Garbage First (G1) 收集器
-
Java垃圾回收的是没有对象引用的内存,而不是对象
- 内存:分为年轻代和老年代
- 年轻代:新分配的对象
- Eden
- Survivor
- from
- to
- 老年代:垃圾回收存活下来的年轻代
-
聊聊JVM的年轻代 http://ifeve.com/jvm-yong-generation/
http://blog.jobbole.com/80499/ -
JVM内存结构划分为不同的内存区,其中一部分内存区和JVM的生命周期保持一致,一部分和线程的声明周期保持一致。尽管不同的内存分区在存储类型和声明周期上有一定区别,却拥有一个相同的本质:存储程序的运行时数据。
-
JVM内存分区根据受访权限的不同分为:线程共享和线程私有两大类。
-
线程共享内存区是指允许被所有线程共享访问的一类内存区,包括堆区、方法区、运行时常量池
- Java堆区
- Java堆区在JVM启动时创建,是一块用于存储对象实例的内存区,同时也是GC执行垃圾回收的重点区域,为了降低GC的回收频率和提升GC的回收效率,可以将生命周期长的Java对象从heap中移至heap外,同样逃逸分析和栈上分配等优化技术也是降低GC回收频率和提升GC回收效率的一种方式。
- 存储在JVM中的Java对象可以被分为两类:一类是生命周期较短的瞬时对象,一类是生命周期长的对象。因此针对不同生命周期的对象,应该采取不同的垃圾收集策略,分代收集由此诞生。目前几乎所有的JVM都采用分代收集算法。
- Java堆区还可分为新生代、老年代
- 新生代又可以划分为Eden空间、From Survior空间、To Survior空间
- **方法区 **
- 在HotSpot中,方法区仅仅是逻辑上的独立,实际上还是包含在Java堆区内,也就是说,方法区在物理上属于Java堆区的一部分
- 方法区中存储了每一个Java类的结构信息,如:运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容以及类、实例、接口初始化时需要用到的特殊方法等数据。
- 方法区也被称为永久代(Permanent Generation),主要是因为方法区除了可以通过选项“-XX:MaxPermSize”设置内存大小进行动态扩展外,并不会像Java堆区那样频繁被GC执行回收,甚至还可以显示指定是否需要在程序运行时回收方法区中的数据,如果没有指定,GC的回收目标仅针对方法区中的常量池和类型卸载。
- 运行时常量池
- 运行时常量池属于方法区的一部分,一个有效的字节码文件除了包含类的版本信息、字段、方法以及接口等描述信息外,还包含一项信息就是常量池表(Constant Pool Table),那么运行时常量池表就是字节码文件中常量池表的运行时表示形式。
- 当类装载器成功将一个类或接口装载进JVM后,就会创建与之对应的运行时常量池。
- 线程私有内存区是不允许被所有线程共享访问的,只允许被所属的独立线程进行访问的一类内存区,包括PC寄存器、Java栈以及本地方法栈三个内存区。