一,java的“一次编译、到处运行”具体涵义
说的是Java语言跨平台的特性(可在不同的操作系统中运行),是依靠Java虚拟机jvm实现的。
比如说Windows平台和Linux平台都有相应的JDK,安装好JDK后也就有了相应的Java语言的运行环境(jvm)。
所以说不是java语言本身的跨平台,而是在不同平台都可以有让其运行的环境。
二,Java 是解释执行的吗?
我们开发的 Java 的源代码,首先通过 Javac 编译成为字节码.class文件,然后,在运行时,通过 Java 虚拟机(JVM)内嵌的解释器将字节码转换成为最终的机器码。
但是常见的 JVM,比如我们大多数情况使用的 Oracle JDK 提供的 Hotspot JVM,都提供了 JIT(Just-In-Time)编译器,也就是通常所说的动态编译器,JIT 能够在运行时将热点代码编译成机器码,这种情况下部分热点代码就属于编译执行,而不是解释执行。
所以“Java 是解释执行”这个说法并不准确。(既可以先编译再解释执行,也可以直接编译执行)
三,Java 中的异常
java有两大异常:Exception 和 Error ,都是继承了 Throwable 类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch)。
Exception 是程序正常运行中,可以预料的意外情况,可以被捕获进行处理。
Error 是指在正常不大可能出现的情况,绝大部分的 Error 都会导致程序(比如 JVM 自身)处于不可恢复状态。既然是非正常情况,所以不需要捕获,常见的比如 OutOfMemoryError 之类,都是 Error 的子类。
Exception 又分为可检查异常和不检查(运行时)异常
1.可检查异常在源代码里必须显式地进行捕获处理,这是编译期检查的一部分。
2.不检查异常就是所谓的运行时异常,类似 NullPointerException、ArrayIndexOutOfBoundsException 之类,通常是可以编码避免的逻辑错误,程序员自己判断是否需要捕获,并不会在编译期强制要求。
经典异常举例:
ClassNotFoundException和NoClassDefFoundError
1.ClassNotFoundException
Java支持使用反射方式在运行时动态加载类,例如使用Class.forName方法来动态地加载类时,可以将类名作为参数传递给上述方法从而将指定类加载到JVM内存中,如果这个类在类路径中没有被找到,那么此时就会在运行时抛出ClassNotFoundException异常。
原因一般是类名写错了,可以理解为代码问题。
这时异常如果有被try catch程序可以正常运行。
2.NoClassDefFoundError
如果JVM或者ClassLoader实例尝试加载(可以通过正常的方法调用,也可能是使用new来创建新的对象)类的时候却找不到类的定义。要查找的类在编译的时候是存在的,运行的时候却找不到了。这个时候就会导致NoClassDefFoundError.
造成该问题的原因可能是打包过程漏掉了部分类,或者jar包出现损坏或者篡改,总之就是文件问题。解决这个问题的办法是查找那些在开发期间存在于类路径下但在运行期间却不在类路径下的类。
注意点:
尽量不要捕获类似 Exception 这样的通用异常。
不要生吞异常。
不要在try代码块中调用return、break或continue语句,因为finally最后一定会执行的。除非确保finally的存在不会改变函数的返回值。
尽量不要打印异常信息,这是一个比较重的操作,会导致程序变慢
try catch不要包含过长代码,最好是只包括需要检验异常的代码,这样会降低JVM的优化效率。
四,java的四种引用(垃圾回收有关)
在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用。
根据其生命周期的长短,将引用分为4类。
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 虚引用
特点:虚引用也叫幻象引用,不能通过它访问对象!