[TOC]
程序计数器、虚拟机栈和本地方法栈是线程私有的
Java 对象的创建过程
加载
通过名字获取类的二进制流并在内存中生成class对象。
验证
验证二进制流的正确性和安全性 包括文件格式验证,元数据验证,字节码验证以及符号引用验证四个步骤。
准备
给类变量(static)分配空间并完成初始化 注意:如果不是final变量,值均为零值。
解析
将符号引用解析为直接引用,包括类或接口的解析,字段解析,类方法解析,接口方法解析。
初始化
执行类的
()方法,这个方法由所有对静态变量的赋值操作和所有静态代码块组成,虚拟机会保证父类的 ()方法在子类的方法开始之前结束,并且提供线程安全的保证(类似于double check,多个线程同时初始化时只有一个线程进入方法,其他线程阻塞,执行完成后其他线程不会再进入方法) 对象的访问定位的两种方式(句柄和直接指针两种方式)
*String类和常量池 *
String类型的常量池比较特殊。它的主要使用方法有两种:
1
2直接使用双引号声明出来的String对象会直接存储在常量池中。
如果不是用双引号声明的String对象,可以使用String提供的intern方String.intern() 是一个Native方法,它的作用是:如果运行时常量池中已经包含一个等于此String对象内容的字符串,则返回常量池中该字符串的引用;如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用。8种基本类型的包装类和常量池
- Java 基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean;这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。
- 两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。
*如何判断对象是否死亡(两种方法)。 *
引用计数算法和可达性分析算法,目前常用的就是可达性分析算法;
简单介绍强引用,软引用,弱引用,虚引用;
StrongReference
强引用是使用最普遍的引用,如果一个对象具有强引用,那么垃圾回收器绝不会回收它,如:
Object obj = new Object(); // 强引用
当内存空间不足,jvm宁愿抛出OutOfMemoryError错误,也不靠随意回收具有强引用的对象来解决内存不足的问题。如果不使用时,要通过如下方式弱化引用。Eg:
obj = null; // 帮助垃圾回收器回收此对象
SoftReference
如果一个对象只具有软引用,则内存空间组够,垃圾回收期就不会回收它;如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被被程序使用。
软应用可用来实现内存敏感的高速缓存。
String abc = new String(“abc”); //Strong
SoftReference
softRef = new SoftReference (str); //Soft WeakReference
弱引用于软应用的区别在于:只有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收期是一个优先级很低的线程,因此不一定很快发现那些只具有弱应用的对象。
PhantomReference
虚引用顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。
如何判断一个类是无用的类
- 该类所有的实例都已经被回收,也就是说java堆中不存在该类的任何实例。
- 加载该类的ClassLoader已经被回收
- 该类对应的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
垃圾收集有哪些算法,各自的特点
- 标记-清除算法
- 复制算法
- 标记整理算法
分代收集
当前商业虚拟机的垃圾收集都采用分代收集,它根据对象的存活周期的不同将内存划分为几块,一般是把Java堆分为新生代和老年代。
- 在新生代中,每次垃圾收集时都会发现有大量对象死去,只有少量存活,因此可选用复制算法来完成收集
- 老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用标记—清除算法或标记—整理算法来进行回收
GC算法 优点 缺点 存活对象移动 内存碎片 适用场景 引用计数 实现简单 不能处理循环引用 标记清除 不需要额外空间 两次扫描,耗时严重 N Y 老年代 复制 没有标记和清除 需要额外空间 Y N 新生代 标记整理 没有内存碎片 需要移动对象的成本 Y N 老年代 HotSpot为什么要分为新生代和老年代
1、Minor GC是发生在新生代中的垃圾收集,采用的复制算法;
2、新生代中每次使用的空间不超过90%,主要用来存放新生的对象;
3、Minor GC每次收集后Eden区和一块Survivor区都被清空;
4、老年代中使用Full GC,采用的标记-清除算法Minor Gc和Full GC 有什么不同呢?
Minor GC(新生代回收)的触发条件比较简单,Eden空间不足就开始进行Minor GC回收新生代。
Full GC(老年代回收,一般伴随一次Minor GC)则有几种触发条件:
- (1)老年代空间不足
- (2)PermSpace空间不足
- (3)统计得到的Minor GC晋升到老年代的平均大小大于老年代的剩余空间
补充:对象的空间分配和晋升
(1)对象优先在Eden上分配
(2)大对象直接进入老年代
虚拟机提供了-XX:PretenureSizeThreshold参数,大于这个参数值的对象将直接分配到老年代中。因为新生代采用的是复制算法,在Eden中分配大对象将会导致Eden区和两个Survivor区之间大量的内存拷贝。
(3)长期存活的对象将进入老年代对象在Survivor区中每熬过一次Minor GC,年龄就增加1岁,当它的年龄增加到一定程度(默认为15岁)时,就会晋升到老年代中。