Java JVM垃圾回收 JVM调优 老年代 新生代

news2024/11/15 14:11:11

如何判断对象可以回收

引用计数法

  1. 当一个对象被其他对象引用,该对象计数 +1,当某个对象不再引用该对象,其计数 -1
  2. 当一个对象没有被其他对象引用时,即计数为0,该对象就可以被回收

缺点:循环引用时,两个对象的计数都为1,导致两个对象都无法被释放

image

可达性分析算法

Java 虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象扫描堆中的对象,看是否能够沿着 GC Root对象 为起点的引用链找到该对象,找不到,表示可以回收。

首先确定根对象(肯定不能当成垃圾的被回收对象),然后扫描堆,判断每个对象是否直接或间接被根对象引用,如果没有则回收。

可以作为GC Root的对象:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象

  • 方法区中类静态属性引用的对象

  • 方法区中常量引用的对象

  • 本地方法栈中JNI(即一般说的Native方法)引用的对象

  • 所有被同步锁(synchronized关键字)持有的对象

四中引用

image

强引用
  • 只有所有 GC Roots 对象都不通过【强引用】引用该对象,该对象才能被垃圾回收

如上图的A1对象,可以沿着根对象(GC Root)找到的对象都是强引用对象,当C对象和B对象都不直接或间接引用A1对象时,才能被垃圾回收。

软引用(SoftReference)
  • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次出发垃圾回收,回收软引用对象
  • 可以配合引用队列来释放软引用自身

如上图A2,C对象通过软引用,引用了A2对象,如果B对象没有强引用A2对象,在垃圾回收后,内存还是不够,A2对象会被回收

软引用基本使用(堆内存设置为:-Xmx20m ,查看GC详情:-XX:+PrintGCDetails -verbose:gc ):

List<SoftReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    // 存
    SoftReference<byte[]> ref = new SoftReference<>(new byte[4 * 1024 * 1024]);
    list.add(ref);
}
for (SoftReference<byte[]> ref : list) {
    // 取,如果发生内存不足,这里取到的可能是null,因为被回收了
    System.out.println(ref.get());
}

软引用+引用队列基本使用(堆内存设置为:-Xmx20m ):

List<SoftReference<byte[]>> list = new ArrayList<>();
// 引用队列
ReferenceQueue<byte[]> queue = new ReferenceQueue<>();
for (int i = 0; i < 5; i++) {
    // 关联了引用队列,当软引用所关联的byte[]被回收时,软引用自己会加入到 queue 中去
    SoftReference<byte[]> ref = new SoftReference<>(new byte[4 * 1024 * 1024], queue);
    System.out.println(ref.get());
    list.add(ref);
}

// 从队列中获取第一个无用的 软引用对象,并移除
// 因为队列先进先出,第一个出去后,第二个就是第一个
Reference<? extends byte[]> poll = queue.poll();
while (poll != null) {
    list.remove(poll);
    poll = queue.poll();
}

System.out.println("===========================");
for (SoftReference<byte[]> reference : list) {
    System.out.println(reference.get());
}
弱引用(WeakReference)
  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
  • 可以配合引用队列来释放弱引用自身

如上图A3,C对象通过弱引用,引用了A3对象,如果B对象没有强引用A3对象,在垃圾回收时,A3对象会被回收

弱引用基本使用(堆内存设置为:-Xmx20m ):

弱引用与强引用类似,把 SoftReference 换成了 WeakReference

//  list --> WeakReference --> byte[]
List<WeakReference<byte[]>> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    WeakReference<byte[]> ref = new WeakReference<>(new byte[4 * 1024 * 1024]);
    list.add(ref);
    for (WeakReference<byte[]> w : list) {
        System.out.print(w.get() + " ");
    }
    System.out.println();
}
System.out.println("循环结束:" + list.size());
虚引用(PhantomReference)

必须配合引用队列使用,主要配合 ByteBuffffer 使用,被引用对象回收时,会将虚引用入队,由 Reference Handler 线程调用虚引用相关方法释放直接内存

如上图,B对象不再引用 ByteBuffer 对象,ByteBuffer 就会被回收。但是直接内存中的内存还未被回收。这时需要将虚引用对象 Cleaner 放入引用队列中,然后调用它的 clean 方法来释放直接内存。

终结器引用(FinalReference)

无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由 Finalizer 线程通过终结器引用找到被引用对象并调用它的 finalize 方法,第二次 GC 时才能回收被引用对象

如上图,B对象不再引用A4对象。这时终结器对象就会被放入引用队列中,引用队列会根据它,找到它所引用的对象。然后调用被引用对象的finalize方法。调用以后,该对象就可以被垃圾回收了。因为执行finalize方法的线程优先级很低,所以效率很低,不容易被释放内存。

垃圾回收算法

标记清除

Mark Sweep,在虚拟机执行垃圾回收的过程中,先采用标记算法确定可回收对象,然后垃圾收集器根据标识清除相应的内容,给堆内存腾出相应的空间

这里的清除并不是将内存空间字节清零,而是记录这段内存的起始地址,下次分配内存的时候,会直接覆盖这段内存。

  • 速度较快
  • 会造成内存碎片,由于内存不连续,一旦分配较大内存的对象,会造成内存溢出问题

image

标记整理

Mark Compact,在虚拟机执行垃圾回收的过程中,先采用标记算法确定可回收对象,然后整理剩余的对象,将可用的对象移动到一起,使内存更加紧凑,连续的空间就更多。

  • 速度慢
  • 没有内存碎片

image

复制

Copy,将内存分为等大小的两个区域,FROM 和 TO。GC Root 引用的对象会被复制到 TO 中,再回收 FROM 中的对象,然后交换 FROM 和 TO 的内存地址,从而 TO 为空,供下次回收使用。

  • 不会有内存碎片
  • 需要占用双倍内存空间

image

分代垃圾回收

image

  1. 对象首先分配在伊甸园区域
  2. 新生代(伊甸园)空间不足时,触发 Minor GC (小型垃圾回收)
  1. 第一次回收:因为 FROM 中是空的,会将 伊甸园 中强引用的对象存放到 TO 中(垃圾回收复制算法),并将 TO 中的对象“寿命”加1(说明存活了一次),将 伊甸园 中的垃圾清空,最后交换 FROM 和 TO 的引用
  2. 第二次回收:这一次是将 伊甸园 和 FROM 中的强引用的对象存入 TO 中,并将寿命加1,再清除 伊甸园 和 FROM 中的垃圾对象,最后交换 FROM 和 TO 的引用
  3. 第N次回收:与第二次类似…
  1. Minor GC 会引发 Stop The World,暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行
  2. 当对象寿命超过阈值时(可能不用超过阈值),会晋升至老年代,最大寿命是15(4bit,最大值就是 1111,10进制是15)
  3. 当老年代空间不足,会先尝试触发 Minor GC,如果之后空间仍不足,触发 FULL GC,STW的时间更长

相关VM参数

含义参数
堆初始大小-Xms
堆最大大小-Xmx 或 -XX:MaxHeapSize=size
新生代大小-Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size )
幸存区比例(动态)-XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy
幸存区比例-XX:SurvivorRatio=ratio
晋升阈值-XX:MaxTenuringThreshold=threshold
晋升详情-XX:+PrintTenuringDistribution
GC详情-XX:+PrintGCDetails -verbose:gc
FullGC 前 MinorGC-XX:+ScavengeBeforeFullGC

设置JVM参数:

-Xms20M -Xmx20M -Xmn10M -XX:+UseSerialGC -XX:+PrintGCDetails -verbose:gc

public static void main(String[] args) {
}

image

Minor GC:

垃圾回收不是 Full GC 开头的话就是 Minor GC,不会清理老年代中的对象

public static void main(String[] args) {
    ArrayList<byte[]> list = new ArrayList<>();
    list.add(new byte[7 * 1024 * 1024]);    // 7MB
    list.add(new byte[512 * 1024]);         // 512KB
    list.add(new byte[512 * 1024]);         // 512KB
}

image

大对象直接晋升老年代:

当新生代空间不足,老年代空间足够,会将大对象直接晋升为老年代,不用触发垃圾回收

public static void main(String[] args) {
    ArrayList<byte[]> list = new ArrayList<>();
    list.add(new byte[8 * 1024 * 1024]);    // 8MB
}

image

Full GC:

Full GC 回收之后发现内存还是不足,就会报错

public static void main(String[] args) {
    ArrayList<byte[]> list = new ArrayList<>();
    list.add(new byte[8 * 1024 * 1024]);    // 8MB
    list.add(new byte[8 * 1024 * 1024]);    // 8MB
}

image

多线程不会导致主线程崩溃:

堆是共享的,当一个线程因为堆空间不足挂掉时,会立即释放堆空间内存,给其他线程使用

public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
        ArrayList<byte[]> list = new ArrayList<>();
        list.add(new byte[8 * 1024 * 1024]);    // 8MB
        list.add(new byte[8 * 1024 * 1024]);    // 8MB
    }).start();
    System.out.println("sleep....");
    Thread.sleep(1000L);
}

image

垃圾回收器

相关概念:

  • 并行收集:指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态
  • 并发收集:指用户线程与垃圾收集线程同时工作(不一定是并行的可能会交替执行)。用户程序在继续运行,而垃圾收集程序运行在另一个CPU上
  • 吞吐量:即CPU用于运行用户代码的时间与CPU总消耗时间的比值(吞吐量 = 运行用户代码时间 / ( 运行用户代码时间 + 垃圾收集时间 )),例如:虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%

串行单线程

堆内存较小,适合个人电脑

开启串行垃圾回收器:-XX:+UseSerialGC = Serial + SerialOld ,新生代(Serial) ,老年代(SerialOld)

新生代是复制算法,老年代是标记整理,两个分别执行,新生代内存不足时触发新生代的垃圾清理,老年代则触发老年代的。

image

  • 安全点:让其他线程都在这个点停下来,以免垃圾回收时移动对象地址,使得其他线程找不到被移动的对象。
  • 阻塞:因为是串行的,只有一个垃圾回收线程。且在该线程执行回收工作时,其他线程进入阻塞状态。

吞吐量优先

多线程,堆内存较大,多核 cpu,【少餐多食】让单位时间内 STW 的时间最短, 0.2 0.2 = 0.4,垃圾回收时间占比最低,这样就称吞吐量高。

  • -XX:+UseParallelGC ~ -XX:+UseParallelOldGC :开启吞吐量优先垃圾回收,JDK1.8及之后自动开启,开启其中一个,另一个也会被自动开启
  • -XX:+UseAdaptiveSizePolicy :新生代采用自适应大小的策略,动态调整 伊甸园 和 幸存区 的大小
  • -XX:GCTimeRatio=ratio :调整垃圾回收和总时间的占比(默认是99,一般设置19,1 / (1 + ratio),如果ratio是99,虚拟机共运行100分钟,垃圾收集器花掉1分钟,那么吞吐量就是99%)
  • -XX:MaxGCPauseMillis=ms :每次垃圾回收最大暂停毫秒数(默认200毫秒),和上面的冲突
  • -XX:ParallelGCThreads=n :控制 ParallelGC 运行垃圾回收的线程数,默认为 CPU 的核心数

image

响应时间优先

多线程,堆内存较大,多核 cpu,【少食多餐】尽可能让单次 STW 的时间最短, 0.1 0.1 0.1 0.1 0.1 = 0.5

  • -XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld
  • -XX:ParallelGCThreads=n ~ -XX:ConcGCThreads=threads
  • -XX:CMSInitiatingOccupancyFraction=percent :控制CMS垃圾清理的时机,比如设置80,在老年代内存占用到80%的时候,就触发垃圾回收(预留空间给浮动垃圾)
  • -XX:+CMSScavengeBeforeRemark

image

  • 初始标记:标记 GC Roots 能直接到的对象。速度很快,存在Stop The World
  • 并发标记:进行 GC Roots Tracing 的过程,找出存活对象且用户线程可并发执行
  • 重新标记:为了修正并发标记期间因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录。存在Stop The World
  • 并发清理:对标记的对象进行清除回收

G1

Garbage First,JDK 9以后默认使用,而且替代了CMS 收集器

  • 2004 论文发布
  • 2009 JDK 6u14 体验
  • 2012 JDK 7u4 官方支持
  • 2017 JDK 9 默认

适用场景:

  • 同时注重吞吐量(Throughput)和低延迟(Low latency),默认的暂停目标是 200 ms
  • 超大堆内存,会将堆划分为多个大小相等的 Region
  • 整体上是 标记+整理 算法,两个区域之间是 复制 算法

相关 JVM 参数:

  • -XX:+UseG1GC :启动G1,JDK8默认是CMS
  • -XX:G1HeapRegionSize=size
  • -XX:MaxGCPauseMillis=time
垃圾回收阶段

image

新生代伊甸园垃圾回收 –> 内存不足,新生代回收+并发标记 –> 混合收集,回收新生代伊甸园、幸存区、老年代内存 –> 新生代伊甸园垃圾回收(重新开始)

Young Collection

存在Stop The World

分区算法region:分代是按对象的生命周期划分,分区则是将堆空间划分连续几个不同小区间,每一个小区间独立回收,可以控制一次回收多少个小区间,方便控制 GC 产生的停顿时间

E:伊甸园,S:幸存区,O:老年代

image

Young Collection + CM
  • CM:并发标记
  • 在 Young GC 时会对 GC Root 进行初始标记
  • 在老年代占用堆内存的比例达到阈值时,对进行并发标记(不会STW),阈值可以根据用户来进行设定

-XX:InitiatingHeapOccupancyPercent=percent :默认45%

image

Mixed Collection

会对 E、S、O 进行全面垃圾回收

  • 最终标记(Remark)会 STW
  • 拷贝存活(Evacuation)会 STW

-XX:MaxGCPauseMillis=ms :用于指定最长的停顿时间

image

为什么有的老年代被拷贝了,有的没拷贝?因为指定了最大停顿时间,如果对所有老年代都进行回收,耗时可能过高。为了保证时间不超过设定的停顿时间,会回收最有价值的老年代(回收后,能够得到更多内存)

Full GC
SerialGC
  • 新生代内存不足发生的垃圾收集 - minor gc
  • 老年代内存不足发生的垃圾收集 - full gc
ParallelGC
  • 新生代内存不足发生的垃圾收集 - minor gc
  • 老年代内存不足发生的垃圾收集 - full gc
CMS
  • 新生代内存不足发生的垃圾收集 - minor gc
  • 老年代内存不足
  • (并发收集失败的时候会触发Full GC)
G1
  • 新生代内存不足发生的垃圾收集 - minor gc
  • 老年代内存不足
  • (垃圾产生太快,并行标记和复制速度跟不上垃圾产生的速度,退化成串行收集,就会触发Full GC)
Young Collection 跨代引用

新生代回收的跨代引用(老年代引用新生代)问题

image

老年代被划为一个个卡表(一个卡表大约为512K),如果该区域引用了新生代对象,则该区域被称为脏卡。遍历对象是否被强引用时,就可以只关注脏卡的卡表,减少搜索范围,提高效率。

  • 卡表与Remembered Set:Remembered Set 存在于E(新生代)中,用于保存新生代对象对应的脏卡
  • 在引用变更时通过post-write barried + dirty card queue (异步+队列完成脏卡的更新操作)
  • concurrent refinement threads 更新 Remembered Set

image

Remark

重新标记阶段,pre-write barrier + satb_mark_queue

  • 黑色:已被处理,需要保留的
  • 灰色:正在处理中的
  • 白色:还未处理的

image

  1. 在并发标记过程中,有可能A被处理了以后未引用C,但该处理过程还未结束,在处理过程结束之前A引用了C,这时就会用到remark
  2. 之前C未被引用,这时A引用了C,就会给C加一个写屏障,写屏障的指令会被执行,将C放入一个队列当中,并将C变为 处理中 状态
  3. 在并发标记阶段结束以后,重新标记阶段会STW,然后将放在该队列中的对象重新处理,发现有强引用引用它,就会处理它

image

JDK 8u20 字符串去重
  • 优点:节省大量内存
  • 缺点:略微多占用了 cpu 时间,新生代回收时间略微增加

-XX:+UseStringDeduplication :默认打开

String s1 = new String("hello"); // char[]{'h','e','l','l','o'}
String s2 = new String("hello"); // char[]{'h','e','l','l','o'}
  • 将所有新分配的字符串放入一个队列
  • 当新生代回收时,G1并发检查是否有字符串重复
  • 如果它们值一样,让它们引用同一个 char[]
    • 与 String.intern() 不一样,String.intern() 关注的是字符串对象
    • 而字符串去重关注的是 char[]
    • 在 JVM 内部,使用了不同的字符串表
JDK 8u40 并发标记类卸载

所有对象都经过并发标记后,就能知道哪些类不再被使用,当一个类加载器的所有类都不再使用,则卸载它所加载的所有类

-XX:+ClassUnloadingWithConcurrentMark :默认启用

JDK 8u60 回收巨型对象

一个对象大于 region 的一半时,称之为巨型对象

  • G1 不会对巨型对象进行拷贝,回收时被优先考虑
  • G1 会跟踪老年代所有 incoming 引用,这样老年代 incoming 引用为0 的巨型对象就可以在新生代垃圾回收时处理掉

image

JDK 9 并发标记起始时间的调整

并发标记必须在堆空间占满前完成,否则退化为 FullGC

  • JDK 9 之前需要使用 -XX:InitiatingHeapOccupancyPercent
  • JDK 9 可以动态调整: -XX:InitiatingHeapOccupancyPercent 用来设置初始值,进行数据采样并动态调整,总会添加一个安全的空档空间
JDK 9 更高效的回收
  • 250+增强
  • 180+bug修复

https://docs.oracle.com/en/java/javase/12/gctuning

垃圾回收调优

  • 掌握 GC 相关的 VM 参数,会基本的空间调整
  • 掌握相关工具
  • 明白一点:调优跟应用、环境有关,没有放之四海而皆准的法则

调优领域

  • 内存
  • 锁竞争
  • cpu 占用
  • io

确定目标

  • 【低延迟】还是【高吞吐量】,选择合适的回收器
  • CMS,G1,ZGC (低延迟)
  • ParallelGC (高吞吐量)
  • Zing

最快的 GC

答案是不发生 GC

查看 FullGC 前后的内存占用,考虑下面几个问题:

  • 数据是不是太多?(比如一次从数据库查出很多数据)
  • 数据表示是否太臃肿?
    • 对象图 (比如数据查询只查用到的数据)
    • 对象大小 (Object对象最小16字节,Integer对象大约24字节,int只有4字节)
  • 是否存在内存泄漏? (比如一个static Map只存数据不删除数据,可以使用软引用、弱引用、第三方缓存)

新生代调优

新生代的特点:

  • 所有的 new 操作的内存分配非常廉价 (每个线程都有个TLAB thread-local allocation buffffer区域,创建对象时,如果这里有内存,会现在这块区域存放对象)

  • 死亡对象的回收代价是零

  • 大部分对象用过即死

  • Minor GC 的时间远远低于 Full GC

越大越好吗?

-Xmn

Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery). GC is performed in this region more often than in other regions. If the size for the young generation is too small, then a lot of minor garbage collections are performed. If the size is too large, then only full garbage collections are performed, which can take a long time to complete. Oracle recommends that you keep the size for the young generation greater than 25% and less than 50% of the overall heap size.

  • 新生代能容纳所有【并发量 * (请求-响应)】的数据
  • 幸存区大到能保留【当前活跃对象+需要晋升对象】
  • 晋升阈值配置得当,让长时间存活对象尽快晋升
    • -XX:MaxTenuringThreshold=threshold
    • -XX:+PrintTenuringDistribution
Desired survivor size 48286924 bytes, new threshold 10 (max 10)
- age 1: 28992024 bytes, 28992024 total
- age 2: 1366864 bytes, 30358888 total
- age 3: 1425912 bytes, 31784800 total
...

老年代调优

以 CMS 为例

  • CMS 的老年代内存越大越好
  • 先尝试不做调优,如果没有 Full GC 那么已经…,否则先尝试调优新生代
  • 观察发生 Full GC 时老年代内存占用,将老年代内存预设调大 1/4 ~ 1/3
    • -XX:CMSInitiatingOccupancyFraction=percent

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1408255.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全桥RLC模态图具体分析

T0时刻&#xff0c;Q6,Q7,Q1.Q4开通&#xff0c;驱动为高电平&#xff0c;励磁电流线性上升,但是lm电流在to是为负电流&#xff0c;这时刻有给副边提供能量&#xff0c;Ip电流开始上升&#xff0c;这个时候给副边的电流也是从0开始上升,这个能量由励磁电感提供&#xff0c;Co给…

HCIP-BGP实验4

搭建实验拓扑图 要求 1.全网可达 2.isp只能配置IP地址 实验开始 配置IP地址及环回 r1,r2,r9,r10配ipv4地址(以r1为例) [Huawei]sysname r1 [r1]interface g0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.1.1.1 24 [r1-GigabitEthernet0/0/0]q [r1]interface LoopBack 0…

【Foxmail】客户端发送邮件错误:SSL Recv :服务器断开连接, errorCode: 6

Foxmail客户端发送邮件提示&#xff1a;SSL Recv :服务器断开连接, errorCode: 6 错误代码 处理方式&#xff1a; 去邮箱生成新的16位授权码&#xff0c;输入到 密码框 内即可。 注&#xff1a;一旦开通授权码&#xff0c;在Foxmail验证时 密码框 里输入的就是 授权码

Ddosify 作为压测工具的使用指南

文章目录 1. 写在最前面1.1 Kubernetes 监控1.2 Performance Testing 2. 命令行安装 & 使用2.1 安装2.2 使用2.2.1 默认的例子2.2.2 定制的例子 3. Dashboard 安装 & 使用3.1 安装3.2 使用3.2.1 简单使用3.2.3 依赖的服务介绍 4. 碎碎念5. 参考资料 1. 写在最前面 由于…

【单例模式】保证线程安全实现单例模式

&#x1f4c4;前言&#xff1a;本文是对经典设计模式之一——单例模式的介绍并讨论单例模式的具体实现方法。 文章目录 一. 什么是单例模式二. 实现单例模式1. 饿汉式2. 懒汉式2.1 懒汉式实现单例模式的优化&#xff08;一&#xff09;2.2 懒汉式实现单例模式的优化&#xff08…

EI论文复现:考虑冷热运行特性的综合能源系统多时间尺度优化调度程序代码!

适用平台/参考文献&#xff1a;MatlabYalmipCplex&#xff1b; 参考文献&#xff1a;电力系统自动化《含冰蓄冷空调的冷热电联供型微网多时间尺度优化调度》 提出考虑冷热特性的综合能源系统多时间尺度优化调度模型&#xff0c;日前计划中通过多场景描述可再生能源的不确定性…

表白墙网站PHP源码,支持封装成APP

源码介绍 PHP表白墙网站源码&#xff0c;适用于校园内或校区间使用&#xff0c;同时支持封装成APP。告别使用QQ空间的表白墙。 简单安装&#xff0c;只需PHP版本5.6以上即可。 通过上传程序进行安装&#xff0c;并设置账号密码&#xff0c;登录后台后切换模板&#xff0c;适配…

牛客30道题解析精修版

1.异常处理 都是Throwable的子类&#xff1a; ① Exception&#xff08;异常&#xff09;:是程序本身可以处理的异常。 ② Error&#xff08;错误&#xff09;: 是程序无法处理的错误。这些错误表示故障发生于虚拟机自身、或者发生在虚拟机试图执行应用时&#xff0c;一般不需要…

《统计学习方法:李航》笔记 从原理到实现(基于python)-- 第3章 k邻近邻法

文章目录 第3章 k邻近邻法3.1 k近邻算法3.2 k近邻模型3.2.1 模型3.2.2 距离度量3.2.3 k值的选择3.2.4 分类决策规则 3.3 k近邻法的实现&#xff1a;kd树3.3.1 构造kd树3.3.2 搜索kd树 算法实现课本例3.1iris数据集scikit-learn实例kd树:构造平衡kd树算法例3.2 《统计学习方法&a…

把Windows系统装进U盘,到哪都有属于你自己的电脑系统

前言 自从接触到WinPE启动盘之后&#xff0c;小白就突然萌生了一个想法&#xff1a;为啥不能把完整的Windows放进U盘呢&#xff1f; 实际上Windows是可以安装进U盘的&#xff0c;外出的时候带上&#xff0c;只需要有台正常开机的电脑就可以使用属于自己的系统。 这个是早已经…

一分钟教你搭建《幻兽帕鲁》服务器

幻兽帕鲁是一款由Pocketpair开发的开放世界生存游戏&#xff0c;融合了多种玩法的游戏&#xff0c;其独特的题材和画风吸引了很多玩家&#xff0c;越来越多的玩家开始尝试自己搭建服务器&#xff0c;享受更加自由的游戏体验。本文将为大家详细介绍如何从零开始搭建《幻兽帕鲁》…

「 网络安全常用术语解读 」杀链Kill Chain详解

1. 简介 早在2009年&#xff0c;Lockheed Martin公司就提出了杀链(Kill Chain)理论&#xff0c;现在也称之为攻击者杀链(Attacker Kill Chain)。杀链其实就是攻击者进行网络攻击时所采取的步骤。杀链模型包括7个步骤&#xff1a;1侦察 -> 2武器化 -> 3交付 -> 4利用 …

java程序判等问题

注意 equals 和 的区别 对基本类型&#xff0c;比如 int、long&#xff0c;进行判等&#xff0c;只能使用 &#xff0c;比较的是直接值。因为基本类型的值就是其数值。对引用类型&#xff0c;比如 Integer、Long 和 String&#xff0c;进行判等&#xff0c;需要使用 equals 进…

【立创EDA-PCB设计基础】6.布线铺铜实战及细节详解

前言&#xff1a;本文进行布线铺铜实战及详解布线铺铜的细节 在本专栏中【立创EDA-PCB设计基础】前面完成了布线铺铜前的设计规则的设置&#xff0c;接下来进行布线 布局原则是模块化布局&#xff08;优先布局好确定位置的器件&#xff0c;例如排针、接口、主控芯片&#xff…

Sulfo Cy3 hydrazide,磺化-Cy3-酰肼,可用于与生物分子的羰基衍生物偶联

您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;Sulfo-Cyanine3-hydrazide&#xff0c;Sulfo Cy3 hydrazide&#xff0c;Sulfo Cyanine3 HZ&#xff0c;磺化 Cy3 酰肼&#xff0c;磺化-Cy3-酰肼 一、基本信息 产品简介&#xff1a;Sulfo-Cyanine3-hydrazide能够与…

远程连接银河麒麟

目录 一、防火墙服务 二、安装SSH服务 1.验证SSH服务是否安装 2.安装SSH服务 三、启动SSH服务 四、远程连接 1.切换登录用户 2.查看IP地址 3.FinalShell连接 4.切换root用户 前言: 本篇主要讲述在Win10系统中通过FinalShell远程连接银河麒麟桌面操作系统V10 一、防火…

android studio从空白开始

对我来说&#xff0c;真正的第一步是清理电脑C盘。从剩余8G清理到25G&#xff0c;把原来看不顺眼又不敢删的文件夹和软件全删了&#xff0c;删爽了的后果就是&#xff0c;用两天的时间在把一些环境配置慢慢装回来&#xff0c;node.js&#xff0c;jdk&#xff0c;npm。努力把它们…

零基础学习【Mybatis Plus】这一篇就够了

学习目录 1. 快速入门1-1. 常用注解总结 1-2. 常用配置 2. 核心功能3. 扩展功能4. 插件功能 1. 快速入门 1-1. 常用注解 MybatisPlus中比较常用的几个注解如下&#xff1a; TableName: 用来指定表名Tableld: 用来指定表中的主键字段信息TableField: 用来指定表中的普通字段信…

Excel·VBA时间范围筛选及批量删除整行

看到一个帖子《excel吧-筛选开始时间&#xff0c;结束时间范围内的所有记录》&#xff0c;根据条件表中的开始时间和结束时间构成的时间范围&#xff0c;对数据表中的开始时间和结束时间范围内的数据进行筛选 目录 批量删除整行&#xff0c;整体删除批量删除整行&#xff0c;分…

[每日一题] 01.24 - 求三角形

求三角形 n int(input()) count1 (1 n) * n // 2 count2 n * n lis1 [str(i).zfill(2) for i in range(1,count1 1)] lis2 [str(i).zfill(2) for i in range(1,count2 1)]for i in range(0,len(lis2),n):print(.join(lis2[i:i n]))print()for i in range(1,n 1):tem…