1,什么是Java虚拟机?为什么Java被称为是”平台无关的编程语言”?

Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。正是因为有 Java 虚拟机的存在,Java 才能被称为与平台无关的编程语言。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者重新编译。

2,JDK 和 JRE 的区别是什么?

JDK:Java 开发工具包,包含了 JRE,编译器和其他工具;例如 javadoc,java调试器; JRE:Java 运行环境,包含 Java 虚拟机和Java 程序所需要的核心类库;如果只想运行 Java 程序,那么只需要安装 JRE,如果要写 Java 程序并运行,那就需要 JDK 了。

3,static 关键字是什么意思?Java 中是否可以覆盖一个 private 或者 static 的方法?

如果一个类的变量或者方法前面有 static 修饰,那么表明这个方法或者变量输入这个类,也就是说可以在不创建对象的情况下直接使用。 当父类的方法被 private 修饰时,表明该方法为父类私有,对其他任何类都是不可见的,因此如果子类定义了一个与父类一样的方法,这对于子类来说相当于是一个新的私有方法,且如果要进行向上转型,然后去调用该”覆盖方法”,会产生编译错误。 static 修饰方法时是静态绑定的,属于类;而覆盖是运行时动态绑定的(动态绑定的多态),因此不能覆盖。

4,Java支持的基本数据类型有哪些?什么是自动拆装箱?

Java 支持的基本数据类型有以下九种:byte,short,int,long

5,JVM 生命周期

Java 程序开始执行时 Java 虚拟机才开始运行,Java 程序结束时,Java 虚拟机就停止。Java 程序总有一个公有的 main() 方法,他是 Java 程序启动的起点,main() 方法所在的线程为初始线程,其他的线程都由初始线程启动。

Java 中的线程分为守护线程(daemon)和普通线程(no-daemon),前者是 Java 虚拟机自己使用的线程,我们也可以通过 setDeamon 将自己创建的线程设置为守护线程。main() 方法的初始线程不属于守护线程,只要 Java 虚拟中还有普通的线程在执行,Java 虚拟机就不会停止。我们可以通过调用 exit() 结束程序。

6,Java 内存泄漏

内存泄漏是指无用对象持续占有内存或无用对象的内存得不到及时释放,从而造成内存空间的浪费。长生命周期的对象持有短生命周期对象的引用就有可能发生内存泄漏,如果短生命周期的对象不再使用了,但是因为长生命周期的对象还在持有它的引用导致短生命周期的对象不能被回收,这样就会导致内存泄漏。一次内存泄漏危害可以忽略,但是内存长期泄漏,会导致可用内存逐渐减少,导致降低性能,最终引发内存溢出。

6.1 静态集合类引起内存泄漏

像 HashMap,Vector 等使用最容易出现内存泄漏,这些静态变量的生命周期和应用程序一致,他们所引用的所有的对象 Object 也不能被释放,因为他们也将一直被 Vector 等引用着。

例如:

  1. static Vector v = new Vector(10);
  2. for (int i = 0; i < 100; i++) {
  3. Object o = new Object();
  4. v.add(o);
  5. o = null;
  6. }

在上面的例子中,循环申请了 Object 对象,并将所有申请的对象放在一个 Vector 中,如果仅仅释放对象 o,那么 Vector 仍然引用该对象,所以这个对象 o 对于 GC 来说是不可以回收的。如果保证 o 能被回收,需要将其从 Vector 中删除,最简单的方法就是将 Vector 对象设置为 null。

6.2 监听器

在 Java 编程中,我们会通过调用一个控件诸如 addXXXListener() 等方法来增加监听器,但是如果在释放对象的时候没有删除该监听器,从而增加内存泄漏的机会。 、

6.3 物理连接

一些物理连接,比如数据库连接和网络连接,因为这些连接是独立于 JVM 的,除非其显示关闭了连接,否则是不会自动被 GC 回收的。Java 数据库一般用 DataSource.getConnection() 来创建连接,当不再使用时必须用 close() 方法来释放。

6.4 内部类引用

内部类的引用是比较容易遗忘的一种,而且一旦没有被释放可能导致一些列的后继类对象没有释放。

6.5 外部模块的引用

例如 A 模块 调用了 B 模块的一个方法:

  1. public void registerMsg(Object b);

这种调用要非常小心,传入了一个对象,很可能模块 B 保持了该对象的引用,此时就需要注意模块 B 是否提供了相应的操作去除引用。

6.6 单例模式

单例对象在初始化后将在 JVM 的整个生命周期中存在(以静态变量的方式),如果单例对象持有外部的引用,那么这个对象将不能被 JVM 正常回收,导致内存泄漏。

  1. public class A {
  2. public A() {
  3. B.getInstance().setA(this);
  4. }
  5. ....
  6. }
  1. class B {
  2. private A a;
  3. private static B instance = new B();
  4. public B(){}
  5. public static B getInstance() {
  6. return instance;
  7. }
  8. public void setA(A a) {
  9. this.a = a;
  10. }
  11. public A getA() {
  12. return a;
  13. }
  14. }

7,Java 内存溢出

内存溢出(Out Of Memory)是指程序在申请内存时,没有足够的内存空间供其使用,从而引起程序终止的现象。当发生内存溢出时,程序将无法进行,强制终止。在 Java 中常见的 java.lang.OutOfMemoryError 就是内存溢出的 log。