首先JVM是动态加载类的,并不是一次性将所有的类加载进来,有个自己的按需加载原则:
- 创建类实例的时候,读取或者设置一个类的静态字段(被final修饰,已在编译期把结果放入常量池的除外),以及调用一个类的静态方法的时候。
- 对类进行反射调用的时候,如果没有进行过初始化则需要先出发其初始化过程。
- 当初始化一个类的时候,如果发现其父类还没有进行过初始化,则需要先出发其父类的初始化过程。
- 当虚拟机启动时,定义了入口(含有main()方法的那个类)的主类,虚拟机会先初始化这个主类。
- 当使用JDK1.7及以上的版本中的动态语言支持时,若一个java.lang.invoke.MethodHandle实例最后的解析结果是:REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法句柄所对应的类没有进行过初始化,则需要先出发它的初始化过程。
当java应用试图加载新类的时候,New Generation、Old Generation处理态度是:能自己解决的就自己解决,自己解决不了就喊GC帮忙,GC帮忙后还是解决不了,新生代(New Generation)将矛盾转移到老生代(Old Generation),如果老生代释放不出来空间,就原地爆炸【out of memery】
详细过程是:
- java应用申请在新生代的伊甸园(Eden)初始化一块空间,如果Eden内存不足,则会喊GC帮忙释放空间
- 如果GC释放之后,还是不足,则会将部分幸存者转移到Survivor区
- 如果Survivor也顶不住了,内存不够了,则将对象转移到老生带中去
- 如果老生带也顶不住了,则会喊GC来大扫除(Full GC)
- 如果大扫除之后还是无法存放Survivor转移的对象,则原地爆炸(out of memery)
新生代中垃圾回收采用复制算法,老生代中采用标记回收算法.
总结:能干的了就干,干不了就GC,GC干不了就GG