常见术语
JMM:JAVA 内存模型(java memory model)。
JNI:jAVA本地接口(Java Native Interface)。
Minor GC:新生代GC。
Major GC:老年代GC。
什么是GC,为什么要有GC
GC即垃圾回收。个人理解,GC的产生是因为内存处理是一个很容易出错的地方。GC可以自动管理内存,自动监控回收垃圾,避免由于垃圾释放程序编写异常等程序问题甚至导致系统崩溃。能更多关注于业务代码实现。
如何判断一个对象是否存活
在hotspot虚拟机中,通过可达性分析来判断一个对象是否失效。可达性分析为:根据GC Roots作为起始节点,寻找对象是否在搜索链中,未在搜索链中的为不可达。将其做一次标记。这个地方需要注意:对象不可达并不意味着一个对象真正的死亡,真正判定对象死亡,还需要进行第二次标记:即该对象是否有必要执行finalize方法。若对象未覆盖的finalize方法或者已执行过,则认为对象已死。因此,对象逃脱死亡的最后一次机会,即在finalize中重新加入到引用链中。
finalize什么时候被调用
当该方法需要被回收时,就会被调用。
在java中,对象什么时候可以被垃圾回收
1、判断对象已死 2、对象所在区域进行gc回收
垃圾回收的基本原理是什么,垃圾回收器可以马上回收内存吗,有什么办法通知虚拟机回收
垃圾回收,从算法来讲,分为三种:
标记-清除算法 ,分为“标记”和“清除”两个阶段;
标记-复制算法 ,将可用内存按分为大小相等的两块,每次只用其中一块,当这块内存用完了,就将还存活的复制到另外一块去,然后将原来的内存清理掉;
标记-整理算法 ,将所有存活的对象都移向内存空间的另外一端,直接清理掉边界以外的内存;
垃圾收集器,在hotspot里面,运行稳定的商用GC回收器有7种,均认为是分代垃圾收集器,其中新生代的三种(serial,Parnew,Parallel Scavenge),老年代的三种(serial old,CMS,Parallel Old),G1收集器贯穿新生、老年代。
在分代收集器里面,垃圾收集器并不是马上回收内存的,触发垃圾回收,需要达到一定的条件,比如CMS收集器,需要占用内存达到其设置的阈值,才能触发回收。
可以通过手动编写System.gc()通知虚拟机回收,但是此时并不一定会触发gc回收。
Java中会存在内存泄漏吗,请简单描述
会产生,比如创建了一个对象,但是后续不再使用,但是该对象的引用一直,长久下来,就会导致内存泄漏。例子:在一个hashSet里面,一直放置对象,就可能导致内存泄漏。
如果对象的引用被置为null,垃圾收集器是否会立即释放对象占用的内存
不会。垃圾收集器会在需要GC时,才会开始进行内存的释放。
什么是分代垃圾回收,它是如何工作的
分代垃圾回收,是将垃圾按物理区域或者逻辑区域(G1)划分为新生代、老年代,通过划分的区域,使用不同的gc收集器进行垃圾回收。新生代,存放新生绝大多数对象的地方,老年代,存放经过多次gc后的对象。由于新生对象大多数符合“朝生夕灭”的特点,固需要一个高效的算法,并较为频繁的做垃圾回收。老年代,相对新生代里的新生对象来说,已经是通过多次新生代GC存活下来的”幸存者“,相对gc次数少于新生代。另外需要注意的是,大对象,是直接放入老年代的,而不是新生代。
serial收集器和吞吐量收集器的区别是什么
两者都是新生代收集器,都使用的复制算法进行垃圾收集。
serial收集器,是客户端默认的gc收集器。是单线程的,由于其单线程的特点,固在gc时,会造成停顿。对于单核环境,serial收集器效率是几种新生代收集器中效率最高的,它的关注点是:1、简单 2、单cpu单核高效 3、停顿时间短
基于吞吐量的收集器,它是多线程的收集器。重点在于吞吐量,吞吐量=运行用户代码的时间/(运行代码的时间+垃圾收集时间)。侧重对CPU的利用上面。
针对这两种收集器,如果是对用户交互体验,相应时间比较看重的话,建议使用serial,当然,由于其单线程的特性,在配置比较好的服务端显得有点浪费资源,因此可以使用parnew收集器(就是serial的并行版本)。如果是对CPU利用率比较看重,需要尽快完成程序的计算任务,没有多少交互的话,建议使用吞吐量收集器。
JVM的永久代会发生垃圾回收吗
首先,永久代的概念是在1.7以及1.7以前。1.8永久代被元空间所取代。默认元空间是根据实际机器内存来的。而大小为实际内存的元空间,很难出现OOM,也很难a触发到GC。在1.7及其之前的jdk里面,如果永久代空间快满,是会触发full gc并且对该空间进行垃圾回收。
Java类加载过程
类加载,分为:加载、验证、准备、解析和初始化五个阶段
加载:获取二进制流,将其中的静态存储结构转为方法区的运行时数据结构,在内存中生成一个代表这个类的底线,作为方法区这个类的各种数据的访问入口
验证:确保class文件的字节流中包含的信息符合当前虚拟机的要求,包括文件格式验证,元数据验证,字节码验证,符号引用验证
准备:为类变量(static)分配内存并设置类变量初始值的阶段。
解析:将常量池内的符号引用替换为直接引用的过程
初始化:开始执行类中定义的java程序代码
什么是类加载器,类加载器有哪些
类加载器就是,实现获取类的二进制节流动作的代码。
类加载器,从实现语言来讲,分为两种:1,启动类加载器(bootstrap),为虚拟机的一部分 2,其他所有类加载器(java实现),独立于虚拟机。java实现的加载器,可分为:启动类加载器,扩展类加载器,应用程序类加载器
什么是类的双亲委派模型
类的双亲委派模型,要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。如果一个雷加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器完成,只有父类反馈无法加载时,子加载器才会加载。