字节抖音客户端提前批一面20200712

设计模式有了解那些?

写单例模式的代码

Java的四种引用类型

进程和线程的区别

volitile关键字是什么意思

进程中的sleep/wait/join/yeild方法分别有什么作用

Android有了解吗?安卓上的MVC、M什么的有了解吗?

一个ArrayList<String str> 里面删除所有特定的字符串要怎么做

编程题:

求两个单链表的交叉点

腾讯视频后台实习面试20200605 0611 0615

第一场:0605

编程题:int数组,每个数在0-9之间,如果值允许交换一次,让交换之后的值最大,输出这个值。e.g. 99788 -> 99887

java什么样的东西可以叫做垃圾?

Treemap和Hashmap底层有什么区别?

什么是Hash冲突?

rehash是什么?什么时候扩容?

第二场:0611

在项目中有遇到过什么问题,如何解决的,效果如何,有什么收获和总结。

如果服务器并发任务过多的时候,如何处理保证服务器不容易崩溃?

数据库有几千个字段,要实现自定义导出的功能如何实现?

用户自定义的导出需求可能不会命中索引,会导致慢查询如何规避?

数据库的两种存储引擎的MYSIAM和InnoDB的区别?

B+树有什么特点,为什么不用红黑树?

在内存存储的时候为什么使用红黑树而不使用B+树呢?

B+树和红黑树查找的时间复杂度是多少?

离开框架来说,如果要开发一个服务,你需要开发的是单进程的服务还是多进程的服务,多线程的服务还是协程的服务,这几种选择有什么区别?如何选择?选择的原则是什么?

多进程和多线程如何选择?

TCP和UDP的差别,启动服务选择那种?选择的依据是什么?

TCP的四次回收的time wait阶段是什么?

time wait是主动发起方的状态还是被动方的状态?

编程题:实现字符串数组的排序(字符串比较函数和排序函数)

第三场:0615

上来就是简单介绍下几个项目,聊了聊硕士期间研究方向的东西

项目的问题:简单介绍一下项目(主要是增删改查)

日志的功能是如何实现的?

删除功能是真正使用delete的SQL语句吗?

项目中的权限管理的功能是如何实现的?权限如何指派,是否有从用户中抽象出角色的概念?

字节跳动-教育实习视频面试20200604

编程题1:输入一个数组,每个元素都是10以内的整数,连接在一起表示一个整数,通过调整顺序,获得一个比原来大的最小的数。

Leetcode 31. 下一个排列

编程题2: 3+3*5-1 表达式中只有三中运算符号,加号减号和乘号。在这个表达式中加上括号会产生多少种结果。

数据库用的是单库还是集群?有多少张表?

客户端发出SQL语句到收到结果大概都经历了那些过程?

数据库的客户端和服务器交互的过程中的是单工的还是双工的还是半双工的?

数据库建立的连接是TCP还是UDP?TCP连接有什么特点?可靠的连接怎么理解?可靠有哪些特点?滑动窗口主要用来解决什么问题?

什么时候需要选择TCP,什么时候选择UDP?

跟谁学 2020-0603 视频面试 java后台开发

解释变量的值传递和地址传递

static 修饰符有什么作用

jvm 堆栈结构有哪些,静态变量放在什么位置,虚拟机栈内部结构,基本数据类型变量值存放的具体位置

Hashmap底层数据结构、何时扩容,为什么用红黑树,数组长度为什么是2的幂次

Hashmap是线程安全的吗,成环的现象如何理解?ConcurrentHashmap的结构,JDK8中的改进是什么。

线程池有了解吗,线程池的参数都有哪些

解释一下BIO和NIO的区别,如何理解阻塞

AOP是什么解释一下

Spring中的对象生命周期是怎么样的

vim中如何撤销操作

Mysql默认的隔离级别是什么

简单介绍一下索引

最左匹配原则是什么意思

TCP的三次握手,为什么不是两次握手?

手撕算法:不用额外空间的前提下,删除一个int数组中的值为target的所有元素,并把剩余元素全部整理到数组前端,后段空余的位置补零

复习:Java虚拟机 JVM底层结构

学习内容来自尚硅谷宋红康老师的JVM教程

https://www.bilibili.com/video/BV1PJ411n7xZ/

类的加载过程

  • 加载
    • 通过一个类的全类名获取该类的字节流
    • 将字节流代表的静态结构转换为方法区的运行时数据结构
    • 在内存中生成一个Class对象,作为这个类的各种数据的访问入口
  • 链接阶段
    • 验证:验证字节流中的信息满足虚拟机要求,如cafebabe头
    • 准备:为类变量分配内存,类的赋值默认初始值(非final的静态变量)
    • 解析:将常量池中的符号引用转换为直接引用的过程
  • 初始化:执行类构造器方法clinit方法(如给静态变量进行显式初始化, 静态代码块执行),子类运行前需要先加载父类的clinit方法,该方法是同步的。

类的加载器

两种类型,引导类加载器(Bootstrap Classloader)和自定义类加载器(拓展类加载器,系统类加载器,用户自定义加载器)

  • 引导类加载器在代码中获取不到,使用c、c++实现的,嵌套在jvm内部,主要加载一些java的核心类库,也会加载拓展类加载器和系统加载器
  • 拓展类加载器加载,父类加载器就是引导类加载器,在ClassLoader继承体系下,加载jre/lib/ext下面的jar包
  • 应用程序类加载器(系统类加载器), 父类加载器就是引导类加载器 , 在ClassLoader继承体系下, 是默认的类加载器,我们在代码中写的类都是这个加载的。

用户自定义类加载器在一些特殊情况下使用

双亲委派机制

  • 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行
  • 如果父类的加载器还存在父类的加载器,则进一步加上委托依次递归请求最终达到顶层的启动类加载器,
  • 如果父类加载器可以完成内加载任务就成功返回,倘若腹内加载器都无法完成此任务,此类加载器才会自己尝试去加载,这就是双亲委派模型

反向委派,核心类库是接口,外部jar包是实现类。

优势:避免类的重复加载,保护程序安全,防止核心的API被修改

沙箱安全机制,就是双亲委派机制对核心源代码的保护,不能再核心类库包名下定义main方法。

运行时数据区

本地方法栈、虚拟机栈、程序计数器、堆区、元数据区(方法区/非堆空间)

线程有自己的程序计数器、虚拟机栈、本地方法栈

多个线程共享堆区和方法区(进程独占,生命周期同JVM)

一个JVM实例对应着一个Runtime类的对象。

程序计数器(PC寄存器)

主要用来存储指向下一条指令的地址,也就是即将执行的指令代码,由执行引擎读取下一条指令

线程私有的,生命周期和线程同步,占用内存很小,不会发生OOM错误而且没有GC。

PC寄存器存储地址有什么用呢?因为CPU会不停的切换各个线程,当切换为某个线程之后,就要知道程序从哪里继续执行。

虚拟机栈

JAVA指令是根据栈来设计的,这样的优点是可以跨平台,指令级比较小,编译器容易实现,但是缺点是和基于寄存器的指令性能实现了一定的下降,同样的功能也需要更多的指令。

栈是运行时单位,堆是存储的单位。

虚拟机栈里面存数的是很多的栈桢 stack frame,每一个栈桢对应着一个方法的 。栈顶的栈桢对应着当前方法。

栈是一种快速有效的分配存储方式;访问速度仅次于PC计数器;操作只有两个 ,入站、出站;栈不存在垃圾回收问题.

StackOverFlowError请求的容量超过了虚拟机占允许的最大容量(无限递归)

OutofmemoryError动态拓展虚拟机内存的时候无法申请到足够的内存

JVM栈可以在启动的时候制定大小。

栈中存什么,栈桢(一个内存区块),栈桢和方法是一一对应的关系

当前栈桢–当前方法–当前类

方法的结束方式有两种,第一种正常结束return;第二种方法中出现未捕获的异常,以抛出异常结束。因此有可能栈顶是异常结束,栈底正常结束,因为栈底处理了异常。

每个栈桢的结构有:局部变量表、操作数栈、动态链接、方法返回地址、一些附加信息

局部变量表是一个数字数组,存方法参数和方法体内的局部变量,包括基本数据类型、引用数据类型和返回值类型。不存在安全问题。局部变量表的大小是在编译时期确定的。

局部变量表中的slot(除了long 和double占用两个slot(32bit 一个 slot),其他类型的数据或者引用占用一个slot);成员方法的局部变量表中的第一个元素是this的引用。slot重复利用,作用域小的销毁后重复利用。

成员变量都有默认初始化的过程,而局部变量没有,所以局部变量必须显式地赋值。

操作数栈主要用于保存计算过程中的中间结果,同时作为计算过程中变量临时的存储空间,

在方法执行过程中,根据字节码指令往栈中写入数据或提取数据即入栈或出栈

说操作数栈实际底层肯定是要用具体的数据结构来实现的,然后可以用数组或者列表,这里用的数组。所以需要指定数组的大小,编译时候确定。

动态链接(指向运行时常量池(这个常量池是字节码文件内部的,最终也会放到常量池中)的方法引用)的作用就是将符号引用转换为调用方法的直接引用

为什么需要常量池?提供一些符号和引用便于指令识别,减小字节码文件的冗余,多个字节码文件可以共用方法区的常量池。

方法调用是怎么样的?方法调用也有静态链接和动态链接对应早期绑定和晚期绑定。就是多态。

Lambda表达式引入入让java这种静态类型语言具有了动态类型语言的一些特性以及底层是用invokeDynamic指令来实现的。用值判断变量的类型,而不是用变量类型来约束值的类型是动态类型语言的关键。

虚方法和非虚方法

虚方法如果每次都需要不断向上层父类找实现类,效率会比较低。为了提高性能,建立虚方法表。虚方法在类加载的链接阶段被创建(具体是在解析的阶段)

方法返回地址 调用者的pc计数器的值作为返回地址,即调用方法之后的下一条指令地址。

方法如果正常退出,则正常返回调用者的方法返回地址,如果是异常退出,调用者则根据异常表来定位接下来执行的位置。

一些附加信息 不重要

一些面试题:

栈溢出的情况:stackOverflowError

调整栈的大小,能保证不一出吗?否

垃圾回收设计JVM栈吗?否

分配栈的内存越大越好吗?否

自定义的局部变量是否线程安全?不一定

如果方法的形参是引用类型的变量或者返回值是引用参数类型,则可能是线程不安全的

本地方法接口和本地方法库—–非运行时区的模块

本地方法:Native Method就是一个Java调用非Java代码的接口。为什么要用本地方法?

  • Java应用需要与Java外界环境交互,效率考量
  • Java需要与操作系统的交互,调用c语言实现的接口

本地方法栈

类似于虚拟机栈的作用,就是管理本地方法的调用,也是线程私有的,内存溢出差不多,有StackOverflow和OutOfMemory,也可以设置栈的内存大小。

一个JVM实例只有一个堆内存,堆也是java内存管理的核心区域。Java堆积在juem启动的时候即被串件,其空间大小也就确定了,是JVM 管理最大的一块内存空间。所有的线程共享堆空间(但是堆中可能有线程的私有缓冲区TLAB)

几乎所有的对象实例和数组都在堆空间中,对象的引用在JVM栈中的某个栈帧的局部变量表中。方法运行结束的时候,堆中的对象不会马上被移除,仅仅在垃圾收集的时候才会被移除。

堆是垃圾回收的重点区域。

现在垃圾收集器大部分都基于分代收集理论设计

  • JDK7以及之前:新生区+养老区+永久区
  • JDK8以及之后:新生区+养老区+元空间
  • 永久区/元空间可以理解为方法区。主要先关注新生区和养老区

堆可以手动设置堆空间的大小,默认是电脑内存的1/64,最大的堆内存大小是电脑内存的1/4。建议初始和最大的设置成一样的。

OOM Error 堆中的对象所占的空间超过了堆的大小,则会导致堆空间的溢出。

年轻代和老年代(二者的内存比例可以分配,默认值是1:2)

年轻代有分为:伊甸园区、幸存者1区和幸存者2区(默认比例是8:1:1,但是需要显式指定)

几乎所有的java对象都是在Edan区创建的,大多数的数据都在青年代被销毁。

  • 创建对象的过程,创建的对象默认放在edan区,当edan区满的时候,触发gc,不是垃圾的全部到to区,from区的也会被gc检查,不是垃圾也到to区。
  • from区和to区的数据会维护一个年龄,每次gc之后年龄+1,超过阈值的时候移动到老年区。
  • from区或者to区满的时候不会触发gc,只有edan区满的时候会,当伊甸园区来的对象to区放不下的时候,可以直接放到老年区。
  • 如果老年区也放不下,在老年区执行一次GC,如果还是放不下就报错OOM。

YGC就是MinorGC,MajorGC是OGC/老年代的GC。

GC线程执行会导致用户进程的暂停,所以GC要尽可能少。

分代的原因就是通过统计数据优化垃圾收集器的性能。因为大部分的对象的生命周期都比较短。

TLAB Thread Local Allocation Buffer

堆是线程共享数据,但是存在线程安全问题,加锁会导致效率的下降,因此未每个线程在伊甸园区分配私有缓存区域。(通常这个空间比较小,为伊甸园区的1%。)

伊甸园区过大,会降低MinorGC的效率,过小会导致MinorGC触发的频率过高,影响用户线程,所以设置要平衡一下。

堆是分配对象存储的唯一选择吗?(”是“)

逃逸分析后,如果未逃逸,则可以将对象优化成被栈上分配。

如果new的对象可以在方法外被进行调用,则发生了逃逸。(就是一个作用域的问题)

  • 栈上分配可以在某种程度上来说,加快代码的执行效率,并减少垃圾回收执行的次数,增强用户线程的体验。
  • 同步消除,如果锁通过逃逸分析,仅仅在当前线程被使用,那么不存在同步安全问题,可以消除同步操作。
  • 标量替换,未逃逸的对象,可以从聚合量的形式被打散成标量(基本数据类型),直接在栈上进行分配就可以了。

但是逃逸分析本身也要消耗性能的,总体的提升是有风险的。该技术还不成熟

方法区

方法区是线程共享的,逻辑上是堆的一部分,但是在大部分JVM在实现过程中是和堆分开的。jdk7 叫做永久带,jdk8叫做元空间。

方法区和永久代不严格等价,在hotspotJVM上是等价的。

元空间的使用的内存是本地内存,永久代用的是虚拟机内存。

方法区主要存类型信息,常量,静态变量和JIT代码缓存

类信息:

  • 类的完整定义如类声明、继承、实现情况、修饰符等
  • 域信息(成员变量):名称、类型、权限修饰符、顺序
  • 方法信息:方法名称、返回值类型、参数个数类型、方法字节码、本地变量表、操作数栈、异常表……

全局变量和全局常量的区别,全局常量在编译阶段就赋值完成了(在字节码文件中有体现),而全局变量在类加载链接阶段的prepare阶段才默认初始化,在第三各初始化阶段才显示初始化。

运行时常量池:字节码文件中有常量池,方法区中有运行时常量池。

常量池包括了各种字面量和对类型、域和方法的符号引用。


为什么要改?

  • 永久代的空间是不好确定,容易产生OOM
  • 对永久代的调优的过程是比较困难的

为什么StringTable要调整?因为永久代回收的效率很低,在full gc 的时候会触发,这导致StringTable回收的效率不高,而日常开发中会有大量的字符串被创建,如果不及时回收,会导致永久代空间不足,放到堆里面,回收会比较即使。

区分好对象本身一直是在堆区的,而对象引用变量(存的对象地址)放的位置不同版本有区别。

方法区的垃圾回收主要是常量池中废弃的常量不再使用的类型

方法区中类的回收条件十分苛刻,费力不讨好。

创建对象的方式

  • new
  • Class.newInstance
  • Constructor.newInstance
  • clone(实现Cloneable接口以及浅复制)
  • 反序列化

创建对象的步骤:Object obj = new Object();

对应的字节码:

Code:
stack=2, locals=2, args_size=1
0: new #2 // class java/lang/Object
3: dup
4: invokespecial #1 // Method java/lang/Object.””:()V
7: astore_1
8: return

  • 判断对象对应的类是否加载、链接、初始化
  • 为对象分配内存,计算占用空间的大小(确定的)
    • 内存规整-指针碰撞(整块空间)
    • 内存不规整-空闲分配列表(碎片化的空间)
  • 处理并发问题
  • 初始化分配到的空间(赋默认初始化值)
  • 设置对象头(所属的类,对象的HashCode,对象的GC信息、锁信息)
  • init方法初始化

对象的内存布局:

  • 对象头Header
    • 运行时元数据:哈希值、GC分代年龄、锁状态等
    • 类型指针:指向类元数据
  • 实例数据:从祖宗到自己的各种类型的字段
  • 对齐填充

对象的访问定位:

  • 句柄访问:效率低(间接访问),需要额外内存维护句柄池,栈中的指针稳定,
  • 直接指针(HotSpot采用的方式):效率高,栈中的指针不稳定,节省内存

直接内存

Java Process Memory = Java heap + native memory (其他空间太小了)

执行引擎

解释器和JIT编译器->java是半编译半解释型语言(与javac编译无关)

解释器:效率比较低,但是响应时间快

为什么非要有字节码?不想C语言、C++一步到位?分层思想可以提高各个部分的效率,不用一步到位的考虑,就想OSI网络分层结构一样,应用层不用直接管物理链路层的东西。虽然分层做出了一定性能上的牺牲。

JIT(Just in time)编译器:响应时间慢,但是执行效率高

Java中的编译器:前端编译器、后段编译器

热点代码以及探测方式

JIT编译后的代码缓存在方法区

默认情况下JVM执行引擎是混合模式,可以通过参数制定只运行特定模式。

JIT编译器分为C1(客户端)和C2(服务端)两种

百度消息件后台实习面试20200527

计算机网络结构 TCP/IP 4层结构都有那些。

传输层协议简单介绍一下。

TCP的三次握手和四次挥手,为什么是三次握手,每次握手携带了那些关键信息,都达到了那些目的。

三次握手和四次握手的区别,相同点

http协议的状态码的分类

http 1.0 、1.1 、2.0 的区别

从浏览器输入www.baidu.com 到看到页面的整个流程

DNS解析的详细流程

cname和a记录域名是什么

Linux熟悉吗?通常是怎么杀死进程的

进程号怎么找到的,怎么通过进程名字找进程

说几个你常用的命令,查看cpu-磁盘-内存,top 如何查看具体进程的信息

linux网络相关的命令

操作系统,说说进程和线程

说说堆和栈的区别,进程里面的堆内存和栈内存的区别

Redis和缓存懂吗

索引中的B树和B+树有什么区别

InnoDB和MyiSAM有了解吗,区别是什么。

数据库事务的几个特性,分别介绍一下。

事务有几种隔离级别

InnoDB和Myisam里面锁有什么区别

项目中的Mysql如何部署,有没有分布式

项目介绍,有没有做压力测试,读写的数据量

怎么进行测试,有些测试用例,单元测试?自动化脚本?

项目中的困难点介绍,如何解决点。

阿里健康java后台5-26电话面试

闲聊了下项目上的事情,项目难点,如何解决,有没有关注过底层的细节,是否比较能够实现同一个功能的两个库,以及这两个库各自的优缺点,好是操作的CPU、内存的情况,Hibernate二级缓存之类的东西

JAVA技术相关

线程的状态有那些

java1.8中Hashmap的改进有哪些

为什么用红黑树,你对红黑树的理解

jdk7 中Hashmap为什么会成环,尾插法为什么可以解决线程安全问题吗

spring框架的启动流程?记不太清了。

网易有道后台JAVA研发实习面试 2020-05-25

编程题

求根号2的值要求小数点后10位精确的一个精确度(二分,进阶牛顿迭代)

实现LRU缓存算法,忘了

写一个链表,实现增删改查

面试:

项目相关的不提了

http https的区别,介绍http

是否接触过Redis

java8有那些新特性

java中集合和map简单介绍

hashmap冲突怎么办

jvm的双亲委派类加载

数据库主键和索引的工作原理