首页 > 其他分享 >面试重点

面试重点

时间:2023-02-03 21:22:25浏览次数:29  
标签:收集器 对象 重点 标记 回收 面试 垃圾 CMS

新生代 Eden 与两个 Survivor 区的解释

  1. 为什么会有年轻代
    我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化 GC 性能。你先想想,如果没有分代,那我们所有的对象都在一块,GC 的时候我们要找到哪些对象没用,这样就会对堆的所有区域进行扫描。而我们的很多对象都是朝生夕死的,如果分代的话,我们把新创建的对象放到某一地方,当 GC 的时候先把这块存 “朝生夕死” 对象的区域进行回收,这样就会腾出很大的空间出来。

  2. 年轻代中的 GC
    HotSpot JVM 把年轻代分为了三部分:1 个 Eden 区和 2 个 Survivor 区(分别叫 from 和 to)。默认比例为 8:1, 为啥默认会是这个比例,接下来我们会聊到。一般情况下,新创建的对象都会被分配到 Eden 区 (一些大对象特殊处理), 这些对象经过第一次 Minor GC 后,如果仍然存活,将会被移到 Survivor 区。对象在 Survivor 区中每熬过一次 Minor GC,年龄就会增加 1 岁,当它的年龄增加到一定程度时,就会被移动到年老代中。

因为年轻代中的对象基本都是朝生夕死的 (80% 以上),所以在年轻代的垃圾回收算法使用的是复制算法,复制算法的基本思想就是将内存分为两块,每次只用其中一块,当这一块内存用完,就将还活着的对象复制到另外一块上面。复制算法不会产生内存碎片。

在 GC 开始的时候,对象只会存在于 Eden 区和名为 “From” 的 Survivor 区,Survivor 区 “To” 是空的。紧接着进行 GC,Eden 区中所有存活的对象都会被复制到 “To”,而在 “From” 区中,仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值 (年龄阈值,可以通过 - XX:MaxTenuringThreshold 来设置) 的对象会被移动到年老代中,没有达到阈值的对象会被复制到 “To” 区域。经过这次 GC 后,Eden 区和 From 区已经被清空。这个时候,“From” 和 “To” 会交换他们的角色,也就是新的 “To” 就是上次 GC 前的 “From”,新的 “From” 就是上次 GC 前的 “To”。不管怎样,都会保证名为 To 的 Survivor 区域是空的。Minor GC 会一直重复这样的过程,直到 “To” 区被填满,“To” 区被填满之后,会将所有对象移动到年老代中。

  1. 一个对象的这一辈子
    我是一个普通的 java 对象,我出生在 Eden 区,在 Eden 区我还看到和我长的很像的小兄弟,我们在 Eden 区中玩了挺长时间。有一天 Eden 区中的人实在是太多了,我就被迫去了 Survivor 区的 “From” 区,自从去了 Survivor 区,我就开始漂了,有时候在 Survivor 的 “From” 区,有时候在 Survivor 的 “To” 区,居无定所。直到我 18 岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了 20 年 (每次 GC 加一岁),然后被回收。

  2. 有关年轻代的 JVM 参数
    1)-XX:NewSize 和 - XX:MaxNewSize
    用于设置年轻代的大小,建议设为整个堆大小的 1/3 或者 1/4, 两个值设为一样大。
    2)-XX:SurvivorRatio
    用于设置 Eden 和其中一个 Survivor 的比值,这个值也比较重要。
    3)-XX:+PrintTenuringDistribution
    这个参数用于显示每次 Minor GC 时 Survivor 区中各个年龄段的对象的大小。
    4).-XX:InitialTenuringThreshol 和 - XX:MaxTenuringThreshold
    用于设置晋升到老年代的对象年龄的最小值和最大值,每个对象在坚持过一次 Minor GC 之后,年龄就加 1。

JVM 垃圾回收算法及回收器详解

一、GC Roots
我们先来了解一下在 Java 中是如何判断一个对象的生死的,有些语言比如 Python 是采用引用计数来统计的,但是这种做法可能会遇见循环引用的问题,在 Java 以及 C# 等语言中是采用 GC Roots 来解决这个问题。如果一个对象和 GC Roots 之间没有链接,那么这个对象也可以被视作是一个可回收的对象。

Java 中可以被作为 GC Roots 中的对象有:

虚拟机栈中的引用的对象。
方法区中的类静态属性引用的对象。
方法区中的常量引用的对象。
本地方法栈(jni)即一般说的 Native 的引用对象。
回到顶部
垃圾收集算法
标记 - 清除
标记 - 清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。在标记阶段首先通过根节点,标记所有从根节点开始的对象,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。标记清除算法带来的一个问题是会存在大量的空间碎片,因为回收后的空间是不连续的,这样给大对象分配内存的时候可能会提前触发 full gc。

1、标记清除标记清除

复制算法
将现有的内存空间分为两快,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

2、复制算法复制算法
现在的商业虚拟机都采用这种收集算法来回收新生代,IBM 研究表明新生代中的对象 98% 是朝夕生死的,所以并不需要按照 1:1 的比例划分内存空间,而是将内存分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中的一块 Survivor。当回收时,将 Eden 和 Survivor 中还存活着的对象一次性地拷贝到另外一个 Survivor 空间上,最后清理掉 Eden 和刚才用过的 Survivor 的空间。HotSpot 虚拟机默认 Eden 和 Survivor 的大小比例是 8:1 (可以通过 - SurvivorRattio 来配置),也就是每次新生代中可用内存空间为整个新生代容量的 90%,只有 10% 的内存会被 “浪费”。当然,98% 的对象可回收只是一般场景下的数据,我们没有办法保证回收都只有不多于 10% 的对象存活,当 Survivor 空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保。

复制算法的高效性是建立在存活对象少、垃圾对象多的前提下的。这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。

3、标记 - 整理
标记 - 整理算法是一种老年代的回收算法,它在标记 - 清除算法的基础上做了一些优化。首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单地清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。这种方法既避免了碎片的产生,又不需要两块相同的内存空间,因此,其性价比比较高。

4、分代收集算法
当前商业虚拟机的垃圾收集都采用 “分代收集”(GenerationalCollection)算法,这种算法并没有什么新的思想,只是根据对象的存活周期的不同将内存划分为几块。一般是把 Java 堆分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法。在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用 “标记 - 清理” 或 “标记 - 整理” 算法来进行回收。

5、增量算法
增量算法的基本思想是,如果一次性将所有的垃圾进行处理,需要造成系统长时间的停顿,那么就可以让垃圾收集线程和应用程序线程交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。使用这种方式,由于在垃圾回收过程中,间断性地还执行了应用程序代码,所以能减少系统的停顿时间。但是,因为线程切换和上下文转换的消耗,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降。

二、垃圾回收器
如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。下图展示了 7 种作用于不同分代的收集器,其中用于回收新生代的收集器包括 Serial、PraNew、Parallel Scavenge,回收老年代的收集器包括 Serial Old、Parallel Old、CMS,还有用于回收整个 Java 堆的 G1 收集器。不同收集器之间的连线表示它们可以搭配使用。

1、Serial 收集器
Serial 收集器是最古老的单线程的收集器,它的缺点是当 Serial 收集器想进行垃圾回收的时候,必须暂停用户的所有进程,即 stop the world。到现在为止,它依然是虚拟机运行在 client 模式下的默认新生代收集器,与其他收集器相比,对于限定在单个 CPU 的运行环境来说,Serial 收集器由于没有线程交互的开销,专心做垃圾回收自然可以获得最高的单线程收集效率。

2、Serial Old 收集器
Serial Old 是 Serial 收集器的老年代版本,它同样是一个单线程收集器,使用” 标记-整理 “算法。这个收集器的主要意义也是被 Client 模式下的虚拟机使用。在 Server 模式下,它主要还有两大用途:一个是在 JDK1.5 及以前的版本中与 Parallel Scanvenge 收集器搭配使用,另外一个就是作为 CMS 收集器的后备预案,在并发收集发生 Concurrent Mode Failure 的时候使用。

通过指定 -UseSerialGC 参数,使用 Serial + Serial Old 的串行收集器组合进行内存回收。

3、ParNew 收集器
ParNew 收集器是 Serial 收集器新生代的多线程实现,注意在进行垃圾回收的时候依然会 stop the world,只是相比较 Serial 收集器而言它会运行多条进程进行垃圾回收。

ParNew 收集器在单 CPU 的环境中绝对不会有比 Serial 收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个 CPU 的环境中都不能百分之百的保证能超越 Serial 收集器。当然,随着可以使用的 CPU 的数量增加,它对于 GC 时系统资源的利用还是很有好处的。它默认开启的收集线程数与 CPU 的数量相同,在 CPU 非常多(譬如 32 个,现在 CPU 动辄 4 核加超线程,服务器超过 32 个逻辑 CPU 的情况越来越多了)的环境下,可以使用 -XX:ParallelGCThreads 参数来限制垃圾收集的线程数。

-UseParNewGC: 打开此开关后,使用 ParNew + Serial Old 的收集器组合进行内存回收,这样新生代使用并行收集器,老年代使用串行收集器。

4、Parallel Scavenge 收集器
Parallel 是采用复制算法的多线程新生代垃圾回收器,似乎和 ParNew 收集器有很多的相似的地方。但是 Parallel Scanvenge 收集器的一个特点是它所关注的目标是吞吐量 (Throughput)。所谓吞吐量就是 CPU 用于运行用户代码的时间与 CPU 总消耗时间的比值,即吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)。停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能够提升用户的体验;而高吞吐量则可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。

5、Parallel Old 收集器
Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,采用多线程和” 标记-整理” 算法。这个收集器是在 jdk1.6 中才开始提供的,在此之前,新生代的 Parallel Scavenge 收集器一直处于比较尴尬的状态。原因是如果新生代 Parallel Scavenge 收集器,那么老年代除了 Serial Old (PS MarkSweep) 收集器外别无选择。由于单线程的老年代 Serial Old 收集器在服务端应用性能上的” 拖累 “,即使使用了 Parallel Scavenge 收集器也未必能在整体应用上获得吞吐量最大化的效果,又因为老年代收集中无法充分利用服务器多 CPU 的处理能力,在老年代很大而且硬件比较高级的环境中,这种组合的吞吐量甚至还不一定有 ParNew 加 CMS 的组合” 给力 “。直到 Parallel Old 收集器出现后,” 吞吐量优先 “收集器终于有了比较名副其实的应用,在注重吞吐量及 CPU 资源敏感的场合,都可以优先考虑 Parallel Scavenge 加 Parallel Old 收集器。

-UseParallelGC: 虚拟机运行在 Server 模式下的默认值,打开此开关后,使用 Parallel Scavenge + Serial Old 的收集器组合进行内存回收。-UseParallelOldGC: 打开此开关后,使用 Parallel Scavenge + Parallel Old 的收集器组合进行垃圾回收

6、CMS 收集器
CMS (Concurrent Mark Swep) 收集器是一个比较重要的回收器,现在应用非常广泛,我们重点来看一下,CMS 是一种获取最短回收停顿时间为目标的收集器,这使得它很适合用于和用户交互的业务。从名字 (Mark Swep) 就可以看出,CMS 收集器是基于标记清除算法实现的。它的收集过程分为四个步骤:

初始标记 (initial mark)
并发标记 (concurrent mark)
重新标记 (remark)
并发清除 (concurrent sweep)
注意初始标记和重新标记还是会 stop the world,但是在耗费时间更长的并发标记和并发清除两个阶段都可以和用户进程同时工作。

不过由于 CMS 收集器是基于标记清除算法实现的,会导致有大量的空间碎片产生,在为大对象分配内存的时候,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前开启一次 Full GC。为了解决这个问题,CMS 收集器默认提供了一个 - XX:+UseCMSCompactAtFullCollection 收集开关参数(默认就是开启的),用于在 CMS 收集器进行 FullGC 完开启内存碎片的合并整理过程,内存整理的过程是无法并发的,这样内存碎片问题倒是没有了,不过停顿时间不得不变长。虚拟机设计者还提供了另外一个参数 - XX:CMSFullGCsBeforeCompaction 参数用于设置执行多少次不压缩的 FULL GC 后跟着来一次带压缩的(默认值为 0,表示每次进入 Full GC 时都进行碎片整理)。

不幸的是,它作为老年代的收集器,却无法与 jdk1.4 中已经存在的新生代收集器 Parallel Scavenge 配合工作,所以在 jdk1.5 中使用 cms 来收集老年代的时候,新生代只能选择 ParNew 或 Serial 收集器中的一个。ParNew 收集器是使用 - XX:+UseConcMarkSweepGC 选项启用 CMS 收集器之后的默认新生代收集器,也可以使用 - XX:+UseParNewGC 选项来强制指定它。

由于 CMS 收集器现在比较常用,下面我们再额外了解一下 CMS 算法的几个常用参数:

UseCMSInitatingOccupancyOnly:表示只在到达阈值的时候,才进行 CMS 回收。
CMS 默认启动的回收线程数目是 (ParallelGCThreads+3)/4,如果你需要明确设定,可以通过 - XX:+ParallelCMSThreads 来设定,其中 - XX:+ParallelGCThreads 代表的年轻代的并发收集线程数目。
CMSClassUnloadingEnabled: 允许对元类数据进行回收。
CMSInitatingPermOccupancyFraction:当永久区占用率达到这一百分比后,启动 CMS 回收 (前提是 - XX:+CMSClassUnloadingEnabled 激活了)。
CMSIncrementalMode:使用增量模式,比较适合单 CPU。
UseCMSCompactAtFullCollection 参数可以使 CMS 在垃圾收集完成后,进行一次内存碎片整理。内存碎片的整理并不是并发进行的。
UseFullGCsBeforeCompaction:设定进行多少次 CMS 垃圾回收后,进行一次内存压缩。
一些建议
对于 Native Memory:

使用了 NIO 或者 NIO 框架(Mina/Netty)
使用了 DirectByteBuffer 分配字节缓冲区
使用了 MappedByteBuffer 做内存映射
由于 Native Memory 只能通过 FullGC 回收,所以除非你非常清楚这时真的有必要,否则不要轻易调用 System.gc ()。
另外为了防止某些框架中的 System.gc 调用(例如 NIO 框架、Java RMI),建议在启动参数中加上 - XX:+DisableExplicitGC 来禁用显式 GC。这个参数有个巨大的坑,如果你禁用了 System.gc (),那么上面的 3 种场景下的内存就无法回收,可能造成 OOM,如果你使用了 CMS GC,那么可以用这个参数替代:-XX:+ExplicitGCInvokesConcurrent。

此外除了 CMS 的 GC,其实其他针对 old gen 的回收器都会在对 old gen 回收的同时回收 young gen。

7、G1 收集器
G1 收集器是一款面向服务端应用的垃圾收集器。HotSpot 团队赋予它的使命是在未来替换掉 JDK1.5 中发布的 CMS 收集器。与其他 GC 收集器相比,G1 具备如下特点:

并行与并发:G1 能更充分的利用 CPU,多核环境下的硬件优势来缩短 stop the world 的停顿时间。
分代收集:和其他收集器一样,分代的概念在 G1 中依然存在,不过 G1 不需要其他的垃圾回收器的配合就可以独自管理整个 GC 堆。
空间整合:G1 收集器有利于程序长时间运行,分配大对象时不会无法得到连续的空间而提前触发一次 GC。
可预测的非停顿:这是 G1 相对于 CMS 的另一大优势,降低停顿时间是 G1 和 CMS 共同的关注点,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集上的时间不得超过 N 毫秒。
在使用 G1 收集器时,Java 堆的内存布局和其他收集器有很大的差别,它将这个 Java 堆分为多个大小相等的独立区域,虽然还保留新生代和老年代的概念,但是新生代和老年代不再是物理隔离的了,它们都是一部分 Region(不需要连续)的集合。
虽然 G1 看起来有很多优点,实际上 CMS 还是主流。

GC 相关的常用参数:
Xmx: 设置堆内存的最大值。
Xms: 设置堆内存的初始值。
Xmn: 设置新生代的大小。
Xss: 设置栈的大小。
PretenureSizeThreshold: 直接晋升到老年代的对象大小,设置这个参数后,大于这个参数的对象将直接在老年代分配。
MaxTenuringThrehold: 晋升到老年代的对象年龄。每个对象在坚持过一次 Minor GC 之后,年龄就会加 1,当超过这个参数值时就进入老年代。
UseAdaptiveSizePolicy: 在这种模式下,新生代的大小、eden 和 survivor 的比例、晋升老年代的对象年龄等参数会被自动调整,以达到在堆大小、吞吐量和停顿时间之间的平衡点。在手工调优比较困难的场合,可以直接使用这种自适应的方式,仅指定虚拟机的最大堆、目标的吞吐量 (GCTimeRatio) 和停顿时间 (MaxGCPauseMills),让虚拟机自己完成调优工作。
SurvivorRattio: 新生代 Eden 区域与 Survivor 区域的容量比值,默认为 8,代表 Eden: Suvivor= 8: 1。
XX:ParallelGCThreads:设置用于垃圾回收的线程数。通常情况下可以和 CPU 数量相等。但在 CPU 数量比较多的情况下,设置相对较小的数值也是合理的。
XX:MaxGCPauseMills:设置最大垃圾收集停顿时间。它的值是一个大于 0 的整数。收集器在工作时,会调整 Java 堆大小或者其他一些参数,尽可能地把停顿时间控制在 MaxGCPauseMills 以内。
XX:GCTimeRatio: 设置吞吐量大小,它的值是一个 0-100 之间的整数。假设 GCTimeRatio 的值为 n,那么系统将花费不超过 1/(1+n) 的时间用于垃圾收集。
NewRatio: 设置新生代(包括 Eden 和两个 Survivor 区)与老年代的比值(除去持久代),设置为 3,则新生代与老年代所占比值为 1:3,新生代占整个堆栈的 1/4。

g1 和 cms 介绍 (适合面试)

CMS 垃圾回收器:
CMS 是作用于老年代的并发垃圾回收器 , 使用标记清除算法,工作流程是:初始标记,并发标记,再次标记,并发清除

优点
耗时最长的并发标记和并发清除阶段 gc 线程和用户线程是并发执行的,因此其 STW 时间短,适合对延迟有要求的任务

缺点:
CMS 在老年代使用的是标记清除算法,会产生大量内存碎片
GC 线程与用户线程并发执行,二者会抢占 cpu, 并且会产生浮动垃圾

初始标记阶段会发生短暂的 stw, 用于标记 GCRoot 对象能够直接到达的对象
并发标记阶段 gc 线程根据 GCRoot 对象标记可到到的存活对象,应用程序可以和 gc 线程并行进行,不需要 stw
再次标记阶段会进行 stw, 目的是为了修正因为并发标记阶段应用程序和 gc 线程并发执行产生的浮动垃圾
并发清除阶段 gc 线程清除垃圾对象,gc 线程和应用线程并发执行因此会产生浮动垃圾,在下一次 gc 清理该浮动垃圾

G1 垃圾回收器:
G1 垃圾回收器是一款可以同时管理新生代和老年代,在老年代使用标记整理算法,其最大的特点是将内存划分为多个大小相等 region, 每个 region 都可以作为伊甸区,survivor 区,老年代

优点:
老年代使用标记整理算法,不会产生内存碎片
使用 region, 不会出现新生代或者老年代分配空间过大而造成浪费
每次只选择垃圾对象多的 region, 而不是整个堆,大幅减少了 STW 时间 (但 region 与 region 之间是有依赖关系的,g1 维护了一个 Remembered Set 记忆集记录了 region 的依赖关系,只需要扫描关联的 region, 而不是整个堆)
用于可预测停顿的模型,可以指定 STW 时间 (也就是可预测停顿), 比如在一小时内垃圾回收导致的 "stop the world" 时间不超过一分钟。
G1 垃圾回收过程主要包含三个阶段,

当伊甸区慢时,年轻代使用标记复制算法进行回收
当堆空间的内存占用达到阈值时,老年代使用标记整理算法进行回收,前三个过程和 cms 类似,都为初始标记,并发标记,并发清除,区别在于最终清除阶段,CMS 是并发的,而 G1 会进行 STW, 不是并发的
当老年代占比达到阈值,触发混合回收,为了防止堆内存耗尽,会回收所有年轻代和部分老年代
CMS 和 G1 比较:

G1 和 CMS 都分为 4 个阶段,前三个阶段基本相同都为初始标记,并发标记,再次标记,区别在于最后清除阶段 CMS 是并发的,G1 不是并发的,因此 CMS 最终会产生浮动垃圾,只能等待下次 gc 才能清除
G1 可以管理整个堆,而 CMS 只能作用于老年代,并且 CMS 在老年代使用的是标记清除算法,会产生内存碎片,而 G1 使用标记整理算法,不会产生内存碎片
G1 相比于 CMS 最大的区别是 G1 将内存划分为大小相等的 Region, 可以选择垃圾对象多的 Region 而不是整个堆从而减少 STW, 同时使用 Region 可以更精确控制收集,我们可以手动明确一个垃圾回收的最大时间
补充:

因为耗时最长的并发标记和并发清除 gc 线程和应用线程都是并发执行的,所以总体来看 cms 收集器的 gc 线程和应用线程是并发执行的

G1 之所以能做到回收时间可控,主要是得益于 Region 这个结构。G1 会记录每个 Region 里的对象有多少是垃圾对象,如果要对某个 Region 进行垃圾回收,他会计算出对该 Region 回收的时间,可以回收多少垃圾。

实际上除了 CMS 收集器,其他都不存在只针对老年代的收集。

但是每个 region 之间是有互相引用的依赖关系的!这导致在 MinorGC 的时候会同时对老年代进行扫描(甚至是整个堆扫描),那就会导致 MinorGC 的效率低下,时间变长!
解决方法是:维护一个 Remebered Set 集合来存放各个 Region 之间的引用关系!当进行 GC Roots Tracing 的时候就可以只扫描 set 里的关联 region!而不用全堆扫描啦!!! 在 GC 根节点的枚举范围中加入 Remembered Set 即可保证不对全堆扫描也不会有遗漏了。

标签:收集器,对象,重点,标记,回收,面试,垃圾,CMS
From: https://www.cnblogs.com/big-mouse/p/17090461.html

相关文章

  • HTML面试知识点
    参考自CavsZhouyou/Front-End-Interview-NotebookHTML面试知识点目录目录HTML面试知识点目录DOCTYPE的作用HTML5为什么只需要写<!DOCTYPEHTML>,而不需要引入DTD?H5与H......
  • #yyds干货盘点# LeetCode面试题:无重复字符的最长子串
    1.简述:给定一个字符串s,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为......
  • #yyds干货盘点# LeetCode程序员面试金典: 递归乘法
    题目:递归乘法。写一个递归函数,不使用*运算符,实现两个正整数的相乘。可以使用加号、减号、位移,但要吝啬一些。示例1:输入:A=1,B=10输出:10示例2:输入:A=3,B=4......
  • DevOps与CICD面试题
    DevOps术语和定义1. 什么是DevOps答:用最简单的术语来说,DevOps是产品开发过程中开发(Dev)和运营(Ops)团队之间的灰色区域。DevOps是一种在产品开发周期中强调沟通,集成......
  • Docker面试题
    常规题:1.  Docker 和虚拟机有啥不同?答:Docker 是轻量级的沙盒,在其中运行的只是应用,虚拟机里面还有额外的系统。2.    Docker安全么?答:Docker 利用了Lin......
  • C++开发面试题合集
    1.epoll的工作原理(【360实习】C++开发)epoll是一种I/O事件通知机制,是linux内核实现IO多路复用的一个实现。在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出......
  • 常见Linux运维面试题,你答对了吗?
    学习完Linux技术之后,接下来我们就需要面临找工作的事情。谈到找工作,很多小伙伴肯定好奇,面试官会问些什么问题?本为为大家汇总了一些常见Linux运维面试题,希望能够给大家......
  • 《2023年电力安全监管重点任务》中的网络安全工作要求
    近日,国家能源局综合司印发《2023年电力安全监管重点任务》(以下简称《重点任务》),明确电力安全监管目标,对今年的安全工作进行了部署。2023年电力安全监管目标是杜绝重大以上电......
  • spring面试题
    1.IOC控制反转在一开始设计组件依赖的时候就考虑到未来出现改动的可能性,所有需要import组件的地方都被替换成了接口,任何业务组件都不再直接控制import哪个具体组件,而是把......
  • 面试官:什么是双亲委派模型?
    双亲委派模型是Java类加载器的一种工作模式,通过这种工作模式,Java虚拟机将类文件加载到内存中,这样就保证了Java程序能够正常的运行起来。那么双亲委派模型究竟说的是啥......