Java面试问题之五十五
[百度面试题问题之一]:请分析一下Java的垃圾回收机制中对方法区的回收过程,在何种条件下才会触发GC对方法区进行回收工作。
答:所谓的方法区也就是HotSpot虚拟机中的永久代,Java虚拟机规范中确实说过可以不要求虚拟机在方法区实现垃圾收集机制,而且在方法区回收的“性价比”一般比较低;在堆中,尤其是在新生代中,常规应用进行一次垃圾收集可以回收70%~95%的空间,而永久代的垃圾收集效率远远低于此。但是现存架构中可能大量使用反射、动态代理、CGLib等bytecode框架,以及动态生成JSP和OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具有方法区收集功能,以保证方法(永久代)区不会溢出。
永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。回收废弃常量与回收Java堆中的对象非常类似。以常量池中的字面量的回收为例,假如一个字符串“abc”已经进入常量池中,但是当前系统没有任何一个String对象是叫做“abc”的,换句话说就是没有任何String对象引用常量池中的"abc"常量,也没有其他任何地方引用了这个字面量,如果在这个时候发生内存回收,而且必要的华,这个“abc”常量就会被垃圾回收机制回收。常量池中的其他类(接口)、方法、字段等符号引用也具有类似的过程。
要判断一个常量是否是“废弃常量”比较简单,而判断一个类是否是“无用的类”的条件则相对苛刻许多。一个类在达到以下三个条件时才有可能被垃圾回收器进行回收:
(1)该类所有的实例都已经被回收,也就是Java堆中不存在该类的任何实例。
(2)加载该类的ClassLoader已经被回收了。
(3)该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。
特别注意,虚拟机在一个方法达到上述三个条件之后才会考虑是否对该方法进行回收,并不是达到这些条件后一定对该方法进行回收。
[百度面试问题之二]:请简述在Android中Handler和Looper之间的关系。
答:Handler和Looper之间的关系主要是:
(1)区别:Handler和Looper两者都与MessageQueue打交道,但是Handler是向消息队列发送消息SendMessage(queue.enqueMessage),而Looper则是从消息队列中取出消息(queue.next)。
(2)联系:a、Handler依赖Looper,每个Handler必然有一个mLooper成员变量。它的MessageQueue就是获取的Looper的消息队列,在构造函数中mQueue = Looper.mQueue,即它们共享一个消息队列。b、Looper取出消息后,在执行消息时,实际上是运行Handler的函数体。因为每一个Message类都有一个Handler的参数。Looper在取出消息时,调用的就是这个Handler的HandleMessage()函数。