Java 相关面试问题

4 篇文章 0 订阅
2 篇文章 0 订阅

前言

仅用于知识点简介,详细描述建议百度,主要是一些个人的理解总结,可以在面试时来回答,所以并不是很详细,只是总结~ 后续应该会不断更新

1. JVM 内存区域

  1. 私有区域
    1. 程序计数器:当前线程所执行的字节码的行号指示器,线程独立
    2. 虚拟机栈:java 方法执行的内存模型,就是方法执行时创建的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。
    3. 本地方法区:和 Java Stack 类似,保存 Native 方法服务,减少频繁的C代码构建
  2. 线程共享区
    1. JAVA 堆:线程共享的一块内存区,用以存放对象和数组,也是垃圾收集器的重要回收区域。因此从分代手机算法来看,还可以分为新生代(Eden、From、To)和老年代
    2. 方法区:又称永久代,线程共享,主要存储 JVM 加载的类信息、常量、静态变量、及时编译器编译后的代码。永久带的内存回收的主要目标是针对常量池的回收和类型的卸载
  3. 直接内存

2. 引用的四种类型

  1. 强引用:对象引用,保证可达性,不会被垃圾回收,也是JAVA 内存泄漏的主要原因
  2. 软引用:SoftReference 实现,内存空间不足时回收,用于内存敏感的程序
  3. 弱引用:WeakReference 实现,生命周期比软引用更短,只要GC变回回收
  4. 虚引用:PhantomReference 实现,不能单独使用,需要和引用队列联合使用。主要用于跟踪对象回收状态

3. 类加载机制

共分为 加载 -> 验证 -> 准备 -> 解析 -> 初始化 五个过程
类加载过程

  1. 加载:生成 Class 对象,作为方法区这个类的各种数据入口。加载方法多样,可以Class文件获取,也可以从Zip、jar、aar中获取,也可以在运行时动态生成(动态代理)、也可以由其他文件生成(如jsp转化)
  2. 验证:确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,以及安全性验证
  3. 准备:设定初始值,并分配这些变量所使用的内存空间
  4. 解析:虚拟机将常量池中的符号引用替换为直接引用
    1. 符号引用:目标可能还没加载到内存中,在不同的虚拟机中符号引用是一致的
    2. 直接引用:指向目标的指针,已加载到内存中
  5. 初始化:最后一个阶段,会开始执行类中定义的Java程序代码
  6. 类构造器:用以执行类构造,注意如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法

Map相关

HashMap 的实现
  • 根据 hashCode 值存储数据
  • 非线程安全,可以用Collections 的 synchronizedMap 使 HashMap 具有线程安全的能力,或使用 ConcurrentHashMap。
  1. Java7 实现(数组 + 链表)
    HashMap 实现

    • 大体为一个数组,每个元素是一个单向链表。
    • 每个绿色的块为一个 Entry 的实例,包含 key,value,hash值和用于单向链表的next
    1. capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。
    2. loadFactor:负载因子,默认为 0.75。
    3. threshold:扩容的阈值,等于 capacity * loadFactor
  2. Java8 实现(数组+链表+红黑树)
    基础的实现与Java7基本一致,但是Java7的实现有一个缺点,在碰撞过多时,一个链表长度超过8个后,O(n)的复杂度会大大降低效率,故在元素超过8个之后,会将链表转换为红黑树
    Java8 HashMap 红黑树结构

ConcurrentHashMap 实现

基本实现思路与HashMap差不多,但是支持并发操作。

  • 由一个个Segment组成,代表一个“部分”或“段”

  • 每个Segment通过继承 ReentrantLock 进行加锁,故每次操作会锁住操作的 Segment,以此保证整个Map的线程安全
    ConcurrentHashMap结构

  • 并行度:默认是16个,也就是最多可以16个线程同时访问,只要他们在不同的Segment就可以。

  • ConcurrentHashMap 同样在 Java8引用了红黑树,不再赘述

TreeMap 实现
  • TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器
  • 当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。如果使用排序的映射,建议使用 TreeMap。
  • 在使用 TreeMap 时,key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。

Java锁

  1. 乐观锁:读多写少,并发碰撞可能性低时使用。乐观的加设没有并发碰撞,采用 读-比较-写 的流程,如果比较版本号时不一致,则重新读。采用CAS操作实现
  2. 悲观锁:写多读少,并发碰撞可能性高时使用。读之前先加锁(synchronized 实现),这样别人想访问时就会block直到得到锁
  3. 自旋锁:如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。
    • 与悲观锁的block不同,线程的自旋是需要消耗CPU的,说白了就是让线程占用CPU做无用功空等
    • 这个消耗可能小于内核态用户态切换的消耗,但是也无法保证,所以需要加一个最大等待时间(jdk1.5是固定的,jdk1.6+加入了自适应自旋锁,时间可控),如果超时还无法得到锁,那便进入block状态
  4. synchronized 同步锁:可以把任意一个非null的对象当锁,独占式的悲观锁。
    • 作用于方法时,锁住的是对象的实例(this);
    • 当作用于静态方法时,锁住的是Class实例,又因为Class的相关数据存储在永久带PermGen(jdk1.8 则是 metaspace),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁所有调用该方法的线程;
    • synchronized 作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。它有多个队列,当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中。
  5. Semaphore 信号量
    • 可以通过计数器为1实现互斥锁
    • 通过 Semaphore.acquire() 申请资源(不够会阻塞),Semaphore.release() 归还资源
  6. Atomic 原子变量
    • 除了基本的几个变量之外,还可以使用AtomicReference 的方式讲一个对象的所有操作转化成原子操作
    • ++i 或 i++ 等操作不具有原子性,但是原子变量执行此操作效率更高

Java 反射

  1. 概念:在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法
  2. 反射API
    • Class 类:反射的核心类,可以获取类的属性,方法等信息。
    • Field 类:Java.lang.reflec 包中的类,表示类的成员变量,可以用来获取和设置类之中的属性值。
    • Method 类: Java.lang.reflec 包中的类,表示类的方法,它可以用来获取类中的方法信息或者执行方法。
    • Constructor 类: Java.lang.reflec 包中的类,表示类的构造方法。
  3. 获取Class对象的3种方法
    • (对象).getClass();
    • (类).class;
    • Class.forName(“类的全路径”);
  4. 获取对象的两种方法
    • Class.newInstance() 前提是该类有默认的空构造器
    • Constructor.newInstance() 可以传入参数创建实例

Java 复制

  1. 直接赋值复制
  2. 浅复制:集成Cloneable 并重写 clone() 方法。如果字段是值类型,则会直接复制,如果是引用类型,则会复制引用,即会与原对象使用同一份地址下的属性,一个改都会改。
  3. 深复制:集成Cloneable 并重写 clone() 方法。与浅复制不同的是,引用类型的属性值也会复制一份,不再使用同一份地址的对象,两者不再有相关性。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

俺不理解

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值