字节跳动Java面经

Java基础

一个java程序开始运行的过程

Java程序运行时,必须经过编译和运行两个步骤。首先将后缀名为.java的源文件进行编译,最终生成后缀名为.class的字节码文件。然后Java虚拟机将编译好的字节码文件加载到内存,然后虚拟机针对加载到内存的字节码进行解释执行,显示结果。

什么是类的加载

类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在java堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class 对象。Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口。

类的加载过程

  1. 加载:查找并加载类的二进制数据;
  2. 验证:确保被加载类的正确性;
  3. 准备:为类的静态变量分配内存,并将其初始化为默认值;
  4. 解析:把类中的符号引用转换为直接引用;
  5. 初始化:为类的静态变量赋予正确的初始值;

类加载器作用

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区中的运行时数据结构,在堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口。

双亲委派机制

  1. 定义:就是某个特定的类加载器在接到类的请求时,首先将加载任务委托给父加载器,依次递归,如果父加载器可以完成类加载任务,就成功返回;只有父加载器无法完成此加载任务时,才自己去加载。
  2. 作用:是为了保证Java核心库的类型安全。这种机制能保证不会出现用户自己能定义java.lang.Object类的情况,因为即使定义了,也加载不了。

java8特性

  1. 接口的默认方法和静态方法
  2. 函数式接口FunctionInterface与lambda表达式
  3. 方法引用
  4. Stream
  5. Optional
  6. Date/time API的改进

参考

数据库

聚簇索引和非聚簇索引

  • 聚簇索引表记录的排列顺序和索引的排列顺序一致。
  • 非聚簇索引表记录的排列顺序和索引的排列顺序不一致。

Java并发

常用的几个线程池

  1. newSingleThreadExecutor:创建一个单线程的线程池。
  2. newFixedThreadPool:创建固定大小的线程池。
  3. newCachedThreadPool:创建一个可缓存的线程池。
  4. newScheduledThreadPool:创建一个支持定时以及周期性执行任务的线程池。

Java容器

hashtable为什么线程安全

hashtable绝大部分方法用synchronized关键字进行修饰,不会出现多个线程同时对数据进行操作的情况,因此保证了线程安全性,但是降低了程序的执行效率。

hashmap为什么线程不安全

  • 在jdk1.7中,多线程环境下,扩容时会造成环形链或数据丢失。
  • 在jdk1.8中,多线程环境下,会发生数据覆盖的情况。

计算机网络

https协议

HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。

对称加密算法

发送消息的时候用密钥加密,然后收到消息用同样的密钥解密。

非对称加密算法

有两个密钥,一个叫公钥,一个叫私钥, 公钥加密的数据只能被私钥解密, 同样的, 私钥加密的数据只能被公钥解密。

http报文结构

  • http请求:请求行、请求头部、空行、请求数据
  • http响应:状态行、消息报头、空行、响应正文

参考

Java虚拟机

OOM如何定位

  • 确认是不是内存本身就分配过小:jmap -heap pid
  • 找到最耗内存的对象:jmap -histo:live pid | more
  • 确认是否是资源耗尽

说几个虚拟机指令

  • -Xms20m:最小堆内存
  • -Xmx20m:最大堆内存
  • -Xss2m:栈空间的大小

虚拟机栈可能会发生什么错误

  • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常;
  • 如果虚拟机栈可以动态扩展,当扩展时无法申请到足够的内存时会抛出 OutOfMemoryError 异常。

操作系统

进程和线程的区别

  1. 进程是操作系统分配资源的最小单元。
  2. 线程是操作系统调度的最小单元。
  3. 一个程序至少有一个进程,一个进程至少有一个线程。
  4. 每个进程对应一个JVM实例,多个线程共享JVM里的堆和方法区。
  5. 线程不能看做独立应用,而进程可以。
  6. 进程有独立的地址空间,互不影响,而线程只是进程不同的执行路径。
  7. 进程的切换比线程的切换开销大。

进程、线程、协程的区别

  1. 进程是操作系统资源分配的最小单位,拥有独立的资源和地址空间。
  2. 线程是CPU调度的单位。
  3. 统一进程中的线程是资源共享的。
  4. 协程是用户级别的,程序之间的切换由用户自行处理,节省了CPU的调度时间。