java面试总结
创始人
2024-03-21 00:50:12

文章目录

  • JVM
    • 类的加载过程
    • 类加载器有哪些
    • 什么是双亲委派
    • 双亲委派的好处
    • 如何打破双亲委派
    • java内存模型
    • 栈帧的结构
    • java堆的分代设计
    • 对象内存分配
    • 对应的GC
    • 为什么需要Survivor区?只有Eden不行吗?
    • 为什么要有两个Survivor区
    • 对象创建过程
    • 对象内存布局
    • 对象头Mark Word
    • 对象大小
    • 对象访问方式
    • JVM的GC执行时机是任何时候都可以吗?
    • 常见的垃圾回收器
      • serial:
      • ParNew:
      • Parallel Scavenge
      • Serial Old:
      • Parallel Old
      • CMS
      • G1
    • 垃圾收集器分类
    • 频繁的FullGC是怎么回事
    • CMS并发更新失败的原因
    • 三色标记算法
    • 为什么G1三色标记要用SATB
  • mysql
    • 普通索引与唯一索引的区别
    • mvcc工作机制
  • http
    • http与https的区别
    • https为什么安全
  • 多线程
    • java线程模型
  • 开放性问题
    • 如何设计一个CDN服务器

JVM

类的加载过程

从总的阶段来看,一共分为五个动作,分别是加载、验证、准备、解析、初始化,当然,这几个动作不是依次执行的,像校验,是贯穿整个过程的。
第一步: 加载,这个过程主要完成3件事
    通过一个类的全限定名来获取此类的二进制流
    将二进制流中的静态存储结构,转化为方法区中的运行时数据结构
    在内存中生成一个代表此类的Class对象,作为方法区中访问该对象数据的入口
第二步: 验证,主要分为4个阶段
    文件格式验证:验证文件格式是否符合class文件格式规范(例如文件是否以0XCAFEBABE开头,版本号是否当前虚拟机能够解析等等)
    元数据验证:验证描述信息是否符合JAVA规范(比如这个类是否有父类,是否继承了final修饰的类等等)
    字节码验证:验证方法体的语义是否合法,符合逻辑
    符号引用验证:验证符号引用能否转换成直接引用,包括直接引用能否被当前类所访问
第三步:准备
    为类变量分配内存空间,并赋初始值。
第四步:解析
    将符号引用替换成直接引用
第五步:初始化
    初始化静态变量的值
    执行静态代码块
    初始化当前类的父类

类加载器有哪些

Bootstrap ClassLoader(启动类加载器)
Extension ClassLoader(扩展类加载器)
Application ClassLoader(应用程序加载器)
自定义类加载器

在这里插入图片描述

什么是双亲委派

当需要加载一个类时,先委托父类加载器去完成,如果父类加载器完成不了,才会尝试自己去加载。

双亲委派的好处

安全,防止核心类被外部篡改
避免类重复加载

如何打破双亲委派

重新loadClass方法
设置上下文类加载器

java内存模型

堆: 堆中存放所有new出来的对象
方法区: 类信息、静态变量、常量、即时编译的代码
程序计数器: 记录当前线程运行到哪一步了
本地方法栈: JVM执行native方法的栈
java虚拟机栈: JVM执行java程序的栈
其中,堆,方法区线程共享,其他的线程私有

在这里插入图片描述

栈帧的结构

局部变量表: 方法中定义的局部变量以及方法的入参(局部变量表中的数据不能直接使用,如果要使用的话,必须调用相关指令将其加载到操作数栈中作为操作数使用)
操作数栈: 以压栈和出栈的形式存储操作数的
动态链接: 将常量池中的调用其他方法的符号引用转化为直接引用
方法返回地址

在这里插入图片描述

java堆的分代设计

Young区:年轻代,包含Eden区和Survivor区
Old区: 老年代
在这里插入图片描述

对象内存分配

在这里插入图片描述

对应的GC

Young区: Young GC(minor GC)
Old区: Old GC(major GC)
Young区+Old区: Full GC,这个是当堆内存不足时触发

为什么需要Survivor区?只有Eden不行吗?

因为新生代使用的算法是复制回收算法,如果只有Survivor区,那么回收一次就会被送往Old区
这样会导致Old区很快被填满,触发Old GC(一般Old GC会伴随着Young GC,也就是Full GC)
老年代的空间一般大于新生代,所以消耗的时间比较长
另外老年代使用的回收算法是标记清除与标记压缩,不适合频繁的触发
所以,存在Survivor区的意义在于,对象不会很快被送到Old区,只有回收16次,才会被送往老年代

为什么要有两个Survivor区

其实是为了解决碎片化问题,因为复制算法,必须有有一块连续并空余的内存,Eden区回收一次后进入Survivor区
那么找不到一块连续的空间,去进行复制回收算法。

对象创建过程

  1. 先看该类是否被加载,如果没有被加载,先去加载(到常量池中查询是否有该类的符号引用,并且该Class类是否被初始化完毕)
  2. 分配内存空间
    2.1 分配内存的方式:
        内存连续: 指针碰撞(移动指针偏移位即可)
        内存不连续: 空闲列表(寻找一块能够创建该对象的区域)
        内存的是否连续,跟使用的垃圾回收器有关
    2.2 如果开辟内存期间,存在并发,怎么办
        CAS的方式
        本地线程分配缓存(每个线程有自己独立的空间,在自己独立空间内开辟内存)
  3. 成员变量赋初始值
  4. 设置对象头信息(markword,Class Point)在·
  5. 对象初始化

对象内存布局

对象头: markword、ClassPoint、length(数组独有)
实例数据: 成员变量
对其填充: 保证对象大小满足8字节的整数倍

在这里插入图片描述

对象头Mark Word

在这里插入图片描述

对象大小

名称大小
markword8
ClassPointer默认为4字节,关闭指针压缩为8字节
boolean1
byte1
short2
char2
int4
float4
long8
double8
数组size占4个字节,加上实例数据大小
引用类型开启指针压缩为4,不开启为8
padding8的倍数对齐

对象访问方式

主流的方式有使用句柄跟直接指针两种,HotSpot是使用的直接指针
句柄访问: 变量中存储的是句柄的地址,而句柄中分别存储了对象的类型数据地址(方法区)与对象的实例数据地址(堆)
直接访问: 变量中存储对象的实例数据地址
优缺点:
    句柄访问的方式,如果实例对象地址发生变化,不需要更新变量的地址,但是多了一层访问,访问速度低于直接访问
    直接访问的优点: 访问速度快

  1. 句柄池(先执行一块地址,存储的对象地址与class地址,访问这个对象的地址需要经过两步,但是在gc回收时,效率较高)
    在这里插入图片描述
  2. 直接指针(直接指向对象)
    在这里插入图片描述

JVM的GC执行时机是任何时候都可以吗?

程序执行时,并非所有地方都能停下来GC,只有在特定的位置,才会去去执行GC,这些特定的位置被称为安全点。
这些特定的位置,就是安全点,这些安全点的选定标准是"是否长时间执行"的特性,比如方法调用,循环跳转,异常跳转等
在GC的时候,有两种方案能够让线程准确的停留在安全点上
    抢占式中断: 先让所有线程中断,然后让那些停留在不安全点上的线程跑到安全点上。
    主动试中断: 当需要GC是,设置一个标志,线程执行过程中,当发现这个标志的时候,就会主动挂起线程。
除了在安全点上,还有一些情况,比如线程sleep或者blocked状态,那么安全区域来解决
只要在一个特定区域中,对象引用状态不会发生改变,就可以发起GC,当进入安全区域时,就标记自己已经进入了安全区域,那么,在这段时间发起GC时,就不用管是否在安全点上了

常见的垃圾回收器

在这里插入图片描述

serial:

单线程的垃圾回收器
适合client端使用
优点: 单核效率最高,简单高效
在这里插入图片描述

ParNew:

多线程的垃圾回收器
适合service端使用
优点: 适合多线程使用
对于Serial来说,优化的是STW的时间

在这里插入图片描述

Parallel Scavenge

与Parnew类似,也是多线程的垃圾回收器
不同点在于,更加注重的是吞吐量,可以手动指定吞吐量,也可以自适应

Serial Old:

单线程的垃圾回收器
使用标记整理算法
JDK1.5之前的老年代垃圾回收器或者作为CMS的备选方案

在这里插入图片描述

Parallel Old

多线程的垃圾回收器
与Parallel Scavenge配合,JDK1.6推出。
使用标记整理算法
Parallel Scavenge与Parallel Old配合,用于注重吞吐量的场合

CMS

并发的垃圾回收器
主要是为了优化减少停顿时间
垃圾回收的过程分为了
    初始标记: 主要是找到所有的GC Root,这一步是STW的
    并发标记: 标记这条引用链上的所有对象,这一步是并发执行
    重新标记: 修正并发标记期间产生的变化,这一步是STW的,要比初始标记时间长点,但是远没有并发标记时间长
    并发清除: 并发去清理垃圾,这一步是并发执行的
使用CMS也会产生一些问题
    CMS的线程数的计算公式(CPU数量+3)/4,如果CPU线程数越少,工作线程执行效率越低,例如只有CPU数量只有两个的时候,那么用户线程的工作效率会降低50%
    CMS当老年代分配不下时,会触发Full GC,使用Serial Old单线程垃圾回收器来回收
    CMS采用的是标记清除,所以会产生浮动垃圾,由于工作线程与垃圾回收线程同时运行,那么很有可能会出现明明还有很大空间,但是却找不到一块连续的空间来放这个对象,这时候也会触发Full GC
    CMS的CPU建议在四核以上

在这里插入图片描述

G1

并发的垃圾回收器,可以由用户手动指定停顿时间
垃圾回收过程:
    初始标记
    并发标记
    重新标记
    筛选回收: 根据每个Regin区价值(回收获得的空间大小以及回收所需要的时间)排序,优先回收在用户指定时间内的垃圾

在这里插入图片描述
回收算法: 从两个Regin区间看的话,是采用的复制算法,如果从整体看的话,是标记压缩算法,可以减少内存碎片的产生。
逻辑分代,分为一个一个的Regin区,每一个Regin区可以是为Eden区、Survivor区、Old区,Humongouns可能跨好几个Regin区来存放大对象
G1分成了2048个Regin区,每一个Regin区大小1M-30M之间
Remembered Set中存放的是当前Regin区中,每个对象被哪些对象所引用,这个引用可能跨Rengin
引用关系的记录维护在Remembered Set中,判断存活对象,只需要扫描Remembered Set即可,就不需要扫描整个堆了

在这里插入图片描述

垃圾收集器分类

  • 串行收集器->Serial和Serial Old
    只能有一个垃圾回收线程执行,用户线程暂停。
    适用于内存比较小的嵌入式设备 。
  • 并行收集器[吞吐量优先]->Parallel Scanvenge、Parallel Old
    多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
    适用于科学计算、后台处理等若交互场景 。
  • 并发收集器[停顿时间优先]->CMS、G1
    用户线程和垃圾收集线程同时执行(但并不一定是并行的,可能是交替执行的),垃圾收集线程在执行的时
    候不会停顿用户线程的运行。
    适用于相对时间有要求的场景,比如Web 。

频繁的FullGC是怎么回事

首先发生Full GC说明是老年代满了,那么有如下可能性
    一般Full GC的原因是老年代满了,那么老年代满了又有很多种情况
    1. 年轻代满了,对象直接进入老年代,那么像这种情况,调大Young区
    2. 大对象直接进入老年代
    3. 内存泄漏
    4. 频繁调用System.gc()

CMS并发更新失败的原因

因为并发标记阶段,用户线程与垃圾回收线程同时在运行,那么如果此时新进来对象新生代老年代都放不下,那么就可能导致晋升失败
如果是这种情况,那么有如下几个解决办法
    1. 如果是年轻代设置的太小了,导致对象很容易进入老年代,那么年轻代空间设置的较大点即可
    2. 如果老年代设置的太小了,导致对象放不下,那么老年代设置的大一点
    3. 另外,增加老年代的回收频率

三色标记算法

白色: 未被标记过的对象
灰色: 自身被标记,子节点没有被标记
黑色: 自身与子节点都有被标记
漏标: 满足漏标,必须是黑色对象指向灰色对象,灰色对象指向白色对象,这时候,黑色对象指向白色对象,同时,灰色对象对白色对象的引用消失,这时候就会产生漏标的情况。
那么解决漏标的话,有两种解决方案
    CMS: increment update -> 关注引用增加,也就是将黑色对象重新标记成灰色对象
    G1: SATB -> 关注引用删除,引用删除时,将他加入到栈中,由于有Remembered Set的存在,就不需要扫描整个堆去查找指向白色的引用,效率较高
在这里插入图片描述

为什么G1三色标记要用SATB

SATB是关注的引用删除,当引用删除时,将他加入到一个栈中
当进行回收时,只需要将栈中数据拿出来遍历,并查询Remembered Set就可以解决漏标的问题了,这样就不用扫描整个堆了,效率比较高

mysql

普通索引与唯一索引的区别

mvcc工作机制

http

http与https的区别

https为什么安全

多线程

java线程模型

开放性问题

如何设计一个CDN服务器

  1. 如何确定用户在哪
    根据用户ip地址来判断用户的位置,例如(北京海淀联通)
  2. 如何做分发
    2.1 用户配置域名解析 域名->CDN域名
    2.2 根据用户的位置,指向离用户最近的CDN服务器
    2.3 这台CDN服务器查找是否有该数据,如果没有,去源站获取
  3. 内容管理
    3.1 是否满足用户设置的存储规则,如果不满足直接重定向到源站
    3.2 如果满足规则, 查询是否有该数据,如果有直接返回数据
    3.3 如果没有该数据,从源站中拉取数据存储,并返回给用户

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...