昨天乔戈里被北京沙尘暴重拳出击,今天已经更新热腾腾的腾讯二三面面经!(带答案)...

絮叨

昨天北京沙尘暴,当时下班正好熬过了沙尘暴,于是准备回去,结果刚骑车走了没两步,就下起了雨,下雨就下雨吧,关键是泥雨,于是就成了这幅样子(一幅生无可恋的样子呀)。(笑可以笑,但在看记得点,学弟辛辛苦苦给码字的面经,原创不易哈~)

正文


电话面。这一轮面试貌似没遇到什么大问题,问的问题也不难,没什么太大印象了…

只记得一个关于内存的。

  • GC roots 有哪些类型?

就是那些确保存活的对象,例如

  • 栈中本地变量表中引用的对象;

  • native 方法栈中引用的对象;

  • 方法区(non-heap)中的类静态属性引用的变量;

  • 方法区(non-heap)中的常量引用的对象;

  • 为什么要选定这些对象为 GC roots?

因为 gc 的目的是回收那些不用的对象,这些对象可以确保需要用到,所以肯定就不能回收。

  • 如何判断一个对象不可达?举个具体的例子?

当一个对象到 GC roots 的对象没有任何引用链相连,这个对象就是不可用的,最典型的例子就是

A a = new A();
a = null;

此时 a 开始指向的对象,已经没有 GC roots的对象指向它了,所以它应该被标记为不可达,我们始终注意的是,回收的永远都是堆上的不可用对象,当然它也有自救的机会,就是 A 这个类重写 finalize() 方法,然后在里面加上 B.b = this,这里假设 b 是类 B 的一个静态变量,这样这个对象依旧不会被回收,因为有 GC roots 到它的引用链。

  • 根搜索算法是如何去实现的呢?

HotSpot首先需要枚举所有的GC Roots根节点,虚拟机栈的空间不大,遍历一次的时间或许可以接受,但是方法区的空间很可能就有数百兆,遍历一次需要很久。更加关键的是,当我们遍历所有GC Roots根节点时,我们需要暂停所有用户线程,因为我们需要一个此时此刻的”虚拟机快照”,找到此时此刻的可达性分析关系图。基于这种情况,HotSpot实现了一种叫做OopMap的数据结构,存储GC Roots对象,同时并不是每个指令都会对OopMap进行修改,这样OopMap很庞大,这里Hotspot引入了安全点,safePoint,**只会在Safe Point处记录GC Roots信息。**这也就是 CMS 常说的初始阶段的第一步,先把 GC roots 找到,然后去标记那些与 GC roots 相关的对象,我个人认为在 gc roots 中会标记引用了他的对象的符号引用的位置,这样就能够实现找到 GC roots 相关的对象了,这个跟类加载过程的加载过程的第三个动作一样,在堆上 去 new 一个对象作为一个类的入口,那这个对象肯定是知道方法区中类的位置的,所以就是说引用了 gc roots的对象的引用链都会有记录。

  • 上面说的虚拟机快照是什么东西?

快照,就是存储在这个点上的所有vm的状态,包括内存和硬盘,当然也就包括了方法区中的 GC roots 根节点。

  • 回收的过程是怎样的?

这里以 cms 收集器为代表。

初始标记:先去判断对象的可达性,如果不可达,标记为 dead,然后看是否有继承 finalize 方法,没有的话直接标记为需要 gc,如果继承了看是否是第一次执行,是第一次执行把其标记为 alive,否则标记为 dead。

并发标记:safepoint到达之后,一边继续标记还可以一边让用户并行;

最终标记:在让用户程序并行的过程中,还会产生 gc 的对象,所以还需要再标记一下;

并发清除:多线程清除。

  • 为什么要将对象分为新生代老年代

  • 早期提出这个分代的思想我认为主要是解决 stop the world的时间长度,因为如果时间太长很影响用户体验,所以只去扫可能很快就死亡的那一些块区域是很正常的想法,而老年代由于逃过了很多次gc,说明他是有在被活跃使用的,所以我们在平时的gc的时候可以不去考虑他,这样就加快了gc的速度;

  • 后期由于引入了并行机制,也就是用户进程和垃圾回收进程可以同步进行,并且可以多线程进行回收,那 stop the world 这个时间就不是重点了,重点就在于GC能够应付的应用内存分配速率(allocation rate),也就是说 gc 的回收速度要跟上应用的分配内存的速度,所以这个时候,gc肯定是选择疯狂回收那种回收率很高的区域,其他回收率不高的肯定得等等。

所以,前者是从时间角度考虑,所以我们需要分代,因为扫小区域比扫大区域时间更短;

而后者则是从追赶用户分配内存的角度考虑,需要分代,这样扫的区域的回报率更高。

放一个链接,写的还是比较有条理的:https://allenwu.itscoder.com/java-gc

[1]2020.3.29 15:00 - 17:30 「150 分钟」 腾讯三面

视频面。这一面前面面的还算okay,但是最后代码撕了一个多小时,生死未卜了…

主要问题还是在计算机网络方面吧。

  • 大端小端是什么?详细叙述一下?

大端和小端是指数据在内存中的存储模式,它由 CPU 决定:

  1. 大端模式(Big-endian)是指将数据的低位(比如 1234 中的 34 就是低位)放在内存的高地址上,而数据的高位(比如 1234 中的 12 就是高位)放在内存的低地址上。这种存储模式有点儿类似于把数据当作字符串顺序处理,地址由小到大增加,而数据从高位往低位存放。

  2. 小端模式(Little-endian)是指将数据的低位放在内存的低地址上,而数据的高位放在内存的高地址上。这种存储模式将地址的高低和数据的大小结合起来,高地址存放数值较大的部分,低地址存放数值较小的部分,这和我们的思维习惯是一致,比较容易理解。

为什么有大小端模式之分?

计算机中的数据是以字节(Byte)为单位存储的,每个字节都有不同的地址。现代 CPU 的位数(可以理解为一次能处理的数据的位数)都超过了 8 位(一个字节),PC机、服务器的 CPU 基本都是 64 位的,嵌入式系统或单片机系统仍然在使用 32 位和 16 位的 CPU。

对于一次能处理多个字节的CPU,必然存在着如何安排多个字节的问题,也就是大端和小端模式。以 int 类型的 0x12345678 为例,它占用 4 个字节,如果是小端模式(Little-endian),那么在内存中的分布情况为(假设从地址 0x 4000 开始存放):

内存地址 0x4000 0x4001 0x4002 0x4003 存放内容 0x78 0x56 0x34 0x12

如果是大端模式(Big-endian),那么分布情况正好相反:

内存地址 0x4000 0x4001 0x4002 0x4003 存放内容 0x12 0x34 0x56 0x78

我们的 PC 机上使用的是 X86 结构的 CPU,它是小端模式;51 单片机是大端模式;很多 ARM、DSP 也是小端模式(部分 ARM 处理器还可以由硬件来选择是大端模式还是小端模式)。

  • cookie 和 session的区别

cookie是为会话存储的键值信息,不可跨域名(只能拿到当前域名下的cookie,包含父级域名),有有效期限,是在客户端的浏览器保存。

session是基于内存的缓存技术,用来保存针对每个用户的会话数据,通过session ID 来区分用户,存储于服务器端。

浏览器在第一次请求时,无cookie,然后服务器收到请求后,创建一个 session,用sessionid 标识,将其放入cookie中,然后客户端以后请求都带上cookie,服务器端收到消息后,解析里面的sessionid即可。

  • java nio 中如何解决半包、粘包问题?

对于粘包问题先读出包头即包体长度n,然后再读取长度为n的包内容,这样数据包之间的边界就清楚了。对于半包问题先读出包头即包体长度n,由于此次读取的缓存池长度小于n,这时候就需要先缓存这部分的内容,等待下次read事件来时拼接起来形成完整的数据包

  • 数据库中 varchar 和 char 的区别是什么?

字符串数据类型

MySQL数据类型含义
char(n)固定长度,申请的长度就是最终的长度,类似于静态数组,英文占一个字节,汉字占两个字节
varchar(n)可变长度,类似于可变数组—列表,英文和汉字都占两个字节,实际长度是它的值的实际长度+1
text存储可变长度的非Unicode数据,最大长度为2^31-1个字符。text列不能有默认值,存储或检索过程中,不存在大小写转换,后面如果指定长度,不会报错误,但是这个长度是不起作用的,意思就是你插入数据的时候,超过你指定的长度还是可以正常插入。
  • 经常变化的字段用varchar;

  • 知道固定长度的用char;

  • 尽量用 varchar;

  • 超过255字节的只能用varchar或者text;

  • 能用varchar的地方不用text;

  • 超长的,例如存储整个html用text。

然后就一直在聊项目了 最后出了一道算法题,就是 LeetCode 上的求下一个排列数的变体题,我竟然…紧张了…

面试时的高频面试算法题(如果面试准备时间不够,那么集中把这些算法题做完即可,命中率高达85%+)
下方公众号 小夕学算法 后台回复 666 一个专注用动画漫画结合的方法讲讲算法的原创公众号。

我知道你对着屏幕肯定笑了,在看走一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值