主要是总结Java面试当中经常问到的Java知识点,总结到一篇博客当中,并给出参考解答或者参考链接。

Java知识点

  • java双亲委派机制及作用
  • 什么是双亲委派机制?一个类加载器收到类加载请求之后,首先判断当前类是否被加载过。已经被加载的类会直接返回,如果没有被加载,首先将类加载请求转发给父类加载器,一直转发到启动类加载器,只有当父类加载器无法完成时才尝试自己加载。
  • 顺序
    加载类顺序:BootstrapClassLoader->ExtensionClassLoader->AppClassLoader->CustomClassLoader
    检查加载顺序:CustomClassLoader->AppClassLoader->ExtensionClassLoader->BootstrapClassLoader
  • 作用
    (1)防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
    (2)保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
  • java unsafe类
  • 对于 Java 语言,没有直接的指针组件,一般也不能使用偏移量对某块内存进行操作。这些操作相对来讲是安全(safe)的。但Java中的 Unsafe 类,使 Java 拥有了像 C 语言的指针一样操作内存空间的能力,同时也带来了指针的问题,Java官方也不建议使用的。这个类可以说是 Java 并发开发的基础
  • Unsafe类提供的功能:
    (1)内存管理。包括分配内存、释放内存等。
    (2)非常规的对象实例化。使用allocateInstance()方法可以直接生成对象实例,且无需调用构造方法和其它初始化方法。
    (3)操作类、对象、变量
    (4)数组操作
    (5)多线程同步。包括锁机制、CAS操作等。
    (6)挂起和恢复。这部分包括了park、unpark等方法。
    (7)内存屏障。这部分包括了loadFence、storeFence、fullFence等方法。这是在Java 8新引入的,用于定义内存屏障,避免代码重排序。
    推荐参考 说一说Java的Unsafe类
  • ThreadLocal及其使用场景
  • ThreadLocal是除了加锁这种同步方式之外的一种规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。 
    ThreadLocal是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题。
    ThreadLocal 是线程本地存储,在每个线程中都创建了一个 ThreadLocalMap 对象,每个线程可以访问自己内部 ThreadLocalMap 对象内的 value。
  • 应用场景:经典的使用场景是为每个线程分配一个 JDBC 连接 Connection。这样就可以保证每个线程的都在各自的 Connection 上进行数据库的操作,不会出现 A 线程关了 B线程正在使用的 Connection;
  • 简述AQS
  • AQS(AbstractQuenedSynchronizer)抽象的队列式同步器。AQS是将每一条请求共享资源的线程封装成一个锁队列的一个结点(Node),来实现锁的分配。
  • AQS原理:AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,就暂时获取不到锁的线程加入到队列中,用CLH队列锁实现的。

CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列(虚拟的双向队列即不存在队列实例,仅存在结点之间的关联关系)。AQS是将每条请求共享资源的线程封装成一个CLH锁队列的一个结点(Node)来实现锁的分配。

  • AQS,它维护了一个volatile int state(代表共享资源)和一个FIFO线程等待队列(多线程争用资源被阻塞时会进入此队列)。
    state的访问方式有三种:getState();setState();compareAndSetState();
    参考 AQS原理
  • 简述java创建对象的过程
  1. 检查该指令的参数能否在常量池中定位到一个类的符号引用,并检查引用代表的类是否已被加载、解析和初始化,如果没有就先执行类加载。
  2. 通过检查通过后虚拟机将为新生对象分配内存。
  3. 完成内存分配后虚拟机将成员变量设为零值
  4. 设置对象头,包括哈希码、GC 信息、锁信息、对象所属类的类元信息等。
  5. 执行 init 方法,初始化成员变量,执行实例化代码块,调用类的构造方法,并把堆内对象的首地址赋值给引用变量。
  • Java的异常体系
  • Throwable 是 Java 语言中所有错误或异常的超类,在 Java 中只有 Throwable 类型的实例才可以被抛出(throw)或者捕获(catch),它是异常处理机制的基本组成类型。实例分为 Error 和 Exception 两种。
  • Error 类是指 java 运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象。如果
    出现了这样的错误,除了告知用户,剩下的就是尽力使程序安全的终止。
  • Exception 又有两个分支 , 一个是运行时异常 RuntimeException , 一 个是检查异常 CheckedException。
  • RuntimeException 如 :NullPointerException 、 ClassCastException ;
    RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。 如果出现 RuntimeException,那么一定是程序员代码书写导致的错误.
  • CheckedException 如: I/O 错误导致的 IOException、SQLException。
    CheckedException:一般是外部错误,这种异常都发生在编译阶段,Java 编译器会强
    制程序去捕获此类异常,即会出现要求你把这段可能出现异常的程序进行 try catch