java平台的理解

246 阅读7分钟

典型回答

java本身是一个面向对象的语言,最显著的两个特点,一是所谓的书写一次,到处运行,能够非常容易获得跨平台的能力;另外就是垃圾收集(GC),java通过垃圾收集器,回收分配内存,大部分情况下,程序员不需要自己操心内存的分配和回收。

我们日常会接触到jre和jdk。jre是java运行环境,包含了jvm和java类库,以及一些模块。而jdk可以看做是jre的一个超集,提供了更多的工具,比如编译器,各种诊断工具等。

对于‘java是解释执行’ 这句话,这个说法不是太准确,我们开发的java的源代码,首先通过javac编译成为字节码(byteCode) ,然后,在运行时,通过java虚拟机(jvm)内嵌的解释器将字节码转换成为最终的机器码。但是常见的jvm,比如我们大多数情况下使用的oracle jdk 提供的Hotspot jvm ,都提供了JIT编译器,也就是通常所说的动态编译器,JIT能够在运行时将代码编译成机器码,这种情况下部分热点代码就属于编译执行。

知识扩展:

对于java平台的理解,可以从很多方面简明谈一下。例如:java语言特性,包括泛型,lambda等语言特性,基础类库,包括集合,IO/NIO,网络,并发,安全等基础类库。或者谈谈jvm的一些基础概念机制。比如java的类加载机制。常用的版本JDK(jdk8)内嵌的Class-Loader,例如bootStrap,Application,Extension Class-loader;

Exception和Error

Exception和Error都是继承了Throwable,在java中只有Throwable的实例才会被抛出(throw)或捕获(catch),它是异常处理机制的基本组成类型;

Exception和Error体现了java平台设计者对不同异常情况的分类,Exception是程序正在运行过程中,正常的情况,可能并且被捕获。进行相应处理。

Error是正常情况下,不会出现这种问题,绝大部分Error都会使程序处于非正常,不可恢复状态,既然是非正常情况,所以不便于也不需要捕获,常见的比如outOfMemoryError之类,都是Error的子类

Exception又分为可检查异常和不检查异常,可检查异常在源代码里必须显式地进行捕获处理,这里编译期检查的一部分,前面我介绍的不可查的Error,是Throwable不是Exception

不检查异常就是所谓的运行异常,类似NullPointerException ,ArrayIndexOutOfBoundsException ,通常是可以编译避免的逻辑错误,根据具体需要来判断是否需要捕获,并不会在编译期强制要求。

第一,理解 Throwable、Exception、Error 的设计和分类

第二,理解 Java 语言中操作 Throwable 的元素和实践

掌握最基本的语法,如try-catch-finally,throw,throws关键字等,

谈谈final , finally ,finalize不同点?

final 是可以修饰方法,类,变量的,每个代表的意思也不同。final修饰的class代表不可继承扩展,final的变量是不可修改的。而final的变量也是不可重写的(override)

finally则是java中一个一定要被强制执行的一种机制,我们可以使用try-fianlly或 try-catch-finally来进行类似jdbc关闭或者unlock的操作。

finalize 是基础类 java.lang.Object 的一个方法,他的设计目的主要是保证对象在被垃圾收集前完成特定资源回收,finalize机制现在已经不推荐了使用了,并且在jdk9开始被标记为deprecated。

四种引用:强引用,软引用,弱引用,幻象引用

不同的引用提现主要提现是对象不同的可达性状态和对垃圾收集的影响

强引用:最常见的普遍对象引用,只要还有强引用指向一个对象,就能表明对象还活着,垃圾收集器就不会碰这些对象。对于一个普通的对象,如果没有其他的引用关系,只要超越了引用的作用域。或者显式的将相应(强引用)赋值为null。就可以被垃圾收集了。当然具体的回收时机还是要看垃圾收集策略。

软引用:只有通过软引用才可以访问到对象的状态

弱引用:就是无法通过强引用和软引用访问,只能通过弱引用访问时的状态。十分临近finalize状态的时机,当弱引用被清除时,就符合finalize的条件了。

幻象引用:上面流程图已经很直观了,就是没有强、软、弱引用关联,并且 finalize 过了,只有幻象引用指向这个对象的时候。

所有引用类型,都是通过抽象类java.lang.Reference的子类,提供了get()方法;

除了幻象引用(因为get方法的对象为null),如果对象还没有被销毁,就可以通过get()方法获取原有对象。可以利用弱引用和软引用,可以将他们访问到的对象,重新指向强引用。

1 强引用

特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。

2 软引用

特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。

应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。

3 弱引用

弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

应用场景:弱应用同样可用于内存敏感的缓存。

4 虚引用

特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。 ReferenceQueue queue = new ReferenceQueue (); PhantomReference pr = new PhantomReference (object, queue); 程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。