最全Java JVM调优篇_java jvm简单调优,整理几个重要的C C++知识

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

3 JVM 运行时内存
  • Java 堆从 GC 的角度还可以细分为: 新生代(Eden 区、From Survivor 区和 To Survivor 区)和老年 代

  • 3.1 新生代

    • 3.1.1 Eden 区

      • Java新对象的出生地(如果新创建的对象占用内存很大,直接分配到老年代)。当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
    • 3.1.2 ServivorFrom

      • 上一次GC的幸存者作为这一次GC的被扫描者
    • 3.1.3 ServivorTo

      • 保留了一次MinorGC过程中的幸存者
    • 3.1.4 MinorGC 的过程(复制->清空->互换)

      • MinorGC采用复制算法

        • 1:eden、servicorFrom 复制到 ServicorTo,年龄+1,首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年 龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不 够位置了就放到老年区);
        • 2:清空 eden、servicorFrom然后,清空 Eden 和 ServicorFrom 中的对象;
        • 3:ServicorTo 和 ServicorFrom 互换最后,ServicorTo 和 ServicorFrom 互换,原ServicorTo 成为下一次 GC 时的 ServicorFrom 区。
  • 3.2 老年代

    • 主要存放应用程序中生命周期长的内存对象。
    • 老年代的对象比较稳定,所以MajorGC不会频繁执行。在进行MajorGC前一般都先进行了一次MinorGC,是得有新生代的对象晋升入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。
    • MajorGc采用标记清除算法:首先扫描一次所有的老年代,标记出存活的对象,然后回收没有标记的对象。Major的耗时比价长,因为要扫描再回收。Major会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出OOM(Out of Memory)异常
  • 3.3 永久代

    • 指内存的永久保存区域,主要存放Class和Meta(元数据)的信息,Class在被加载的时候被放入永久区域,它和存放实例的区域不同,GC不会在主程序运行期对永久区域进行清理。所以这也导致了永久代区域会随着加载Class的增多而胀满,最终抛出OOM异常

    • 3.3.1 JAVA8 与元数据

      • 在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入native memory,字符串池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不再由MaxPermSize控制,而由系统的实际可以用空间来控制

4 垃圾回收与算法
  • JVM GC

    • gc要做的三件事

      • 1.哪些内存需要回收?
      • 2.什么时候回收?
      • 3.怎么回收?
    • 哪些对象已经“死亡”

      • 引用计算法(Reference Counting)

        • 循环引用的问题
      • 根搜索算法(GC Roots Tracing)

        • 通过一系列称为GC Roots的电作为起点,向下搜索,当一个对象到任何GC Roots没有引用链相连,说明其已经“死亡”

        • GC Roots

          • VM 栈中的引用
          • 方法区中的静态引用
          • JNI 中的引用
    • 垃圾收集算法

      • 标记清除(Mark-Sweep)

        • 效率低
        • 内存碎片多
      • 复制(Coping)

        • 1-Eden
        • 2-Survivor
      • 标记整理(Mark-Compact)

      • 分代收集(Generational Collecting)

    • 垃圾收集器

      • Serial
      • ParNew
      • Parallerl Scavenge
      • Serial Old
      • Parallel Old
      • CMS-Concurrent Mark Sweep
    • 参数

      • Xms
      • Xmx
      • Xmn
      • -XX:+PrintGCDetails
      • -XX:sURIVORrATIO=8
      • -XX:PretenureSizeThreshold=xxx
      • -XX:MaxTenuringThreshold
  • 4.1 如何确定垃圾

    • 4.1.1引用计数法

      • 在Java中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为0,则说明对象不太可能再被用到,name这个对象就是可回收对象
    • 4.1.2可达性分析

      • 为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果“GC roods”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收
  • 4.2 标记清除算法(Mark-Sweep)

    • 最基础的垃圾胡思后算法,分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。该算法最大的问题就是内存碎片化严重,后续可能发生大对象不能找到可利用空间的问题
  • 4.3 复制算法(copying)

    • 为了解决Nark-Sweep算法内存碎片化的缺陷而被提出的算法。按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,这种算法虽然实现简单,内存效率高,不易产生碎片,但是有最大的问题就是可能内存被压缩到了原本的一半。且存活对象增多的话,Copying算法的效率会大大降低
  • 4.4 标记整理算法(Mark-Compact)

    • 结合了以上两个算法,为了避免缺陷而提出。标记阶段和Mark-Sweep算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象
  • 4.5 分代收集算法

    • 分代收集法师目前大部分JVM所采用的方法。其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将GC堆划分为老生代(Tenured/Old Generation)和新生代(Young Generation)。老生代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法

    • 4.5.1 新生代与复制算法

      • 目前大部分JVM的GC对新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,即要赋值的操作比较少,但通常并不是按照1:1来划分新生代。一般将新生代划分为一块较大的Eden空间和两个较小的Survivor空间(From Space,To Space),每次使用Edenkongjian和其中的一块Survivor空间,当进行回收时,将该两块空间中还存活的对象复制到另一块Survivor空间中
    • 4.5.2 老年代与标记复制算法

      • 而老年代因为每次只回收少量对象,因而采用Mark-Compact算法
      • 1.Java虚拟机提到过的处于方法区的永生代(Permanent Generation),它用来存储class类,常量,方法描述等。对永生代的回收主要包括废弃常量和无用的类
      • 2.对象的内存分配主要在新生代的Eden Space和Surivior的From Space(Survivor目前存放对象的那一块),少数情况会直接分配到老生代
      • 3.当新生代的Eden Space和From Space空间不足时就会发生一次GC,进行GC后,Eden Space和From Space区的存活对象就会被挪到To Space,然后将整个对象存储到老生代
      • 4.如果To Space无法粗狗存储某个对象,则将这个对象存储到老生代。
      • 5.在进行GC后,使用的便是Eden Space和To Space了,如此反复循环
      • 6.当对象在Survivor区躲过一次GC后,其年龄就会+1.默认情况下年龄到达15的对象会被移到老生代中。
  • 4.6 GC 分代收集算法 VS 分区收集算法

    • 4.6.1 分代收集算法

      • 当前主流 VM 垃圾收集都采用”分代收集”(Generational Collection)算法, 这种算法会根据 对象存活周期的不同将内存划分为几块, 如 JVM 中的 新生代、老年代、永久代,这样就可以根据 各年代特点分别采用最适当的 GC算法

      • 4.6.1.1 在新生代-复制算法

        • 每次垃圾回收都能发现大批量对象已死,只有少量存活,因此选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集
      • 4.6.1.2 在老年代-标记整理算法

        • 因为对象存活率高、没有额外空间对它进行分配担保,就必须采用“标记——清理”或“标记——整理”算法来进行回收,不必进行内存复制,且直接腾出空闲内存
    • 4.6.2 分区收集算法

      • 分区算法则将整个堆内存空间划分为连续的不同小区间,每个小区间独立使用,独立回收。这样做的好处是可以控制一次回收多少个小区间,根据目标停顿时间,每次合理地回收若干个小区间(而不是整个堆),从而减少一次GC所产生的停顿
  • 4.7 GC 垃圾收集器

    • Java堆内存被划分为新生代和老年代两部分,新生代主要使用复制和标记——清除垃圾回收算法:老年代主要使用标记——整理垃圾回收算法,因此Java虚拟机中针对新生代和老年代分别提供了多种不同的垃圾收集器

    • 4.7.1 Serial 垃圾收集器(单线程、复制算法)

      • Serial(英文连续)是最基本垃圾收集器,使用复制算法,曾经是 JDK1.3.1 之前新生代唯一的垃圾 收集器。Serial是一个单线程的收集器,它不但只会使用一个 CPU 或一条线程去完成垃圾收集工 作,并且在进行垃圾收集的同时,必须暂停其他所有的工作线程,直到垃圾收集结束。Serial 垃圾收集器虽然在收集垃圾过程中需要暂停所有其他的工作线程,但是它简单高效,对于限 定单个 CPU 环境来说,没有线程交互的开销,可以获得最高的单线程垃圾收集效率,因此 Serial 垃圾收集器依然是 java 虚拟机运行在 Client 模式下默认的新生代垃圾收集器。
    • 4.7.2 ParNew 垃圾收集器(Serial+多线程)

      • ParNew 垃圾收集器其实是 Serial 收集器的多线程版本,也使用复制算法,除了使用多线程进行垃 圾收集之外,其余的行为和 Serial 收集器完全一样,ParNew 垃圾收集器在垃圾收集过程中同样也 要暂停所有其他的工作线程。ParNew 收集器默认开启和 CPU 数目相同的线程数,可以通过-XX:ParallelGCThreads 参数来限 制垃圾收集器的线程数。【Parallel:平行的】ParNew 虽然是除了多线程外和 Serial 收集器几乎完全一样,但是 ParNew 垃圾收集器是很多 java 虚拟机运行在 Server 模式下新生代的默认垃圾收集器。
    • 4.7.3 Parallel Scavenge 收集器(多线程复制算法、高效)

      • Parallel Scavenge 收集器也是一个新生代垃圾收集器,同样使用复制算法,也是一个多线程的垃 圾收集器,它重点关注的是程序达到一个可控制的吞吐量(Thoughput,CPU 用于运行用户代码 的时间/CPU 总消耗时间,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)), 高吞吐量可以最高效率地利用 CPU 时间,尽快地完成程序的运算任务,主要适用于在后台运算而 不需要太多交互的任务。自适应调节策略也是 ParallelScavenge 收 集器与 ParNew 收集器的一个 重要区别。
    • 4.7.4 Serial Old 收集器(单线程标记整理算法 )

      • Serial Old 是 Serial 垃圾收集器年老代版本,它同样是个单线程的收集器,使用标记-整理算法, 这个收集器也主要是运行在 Client 默认的 java 虚拟机默认的年老代垃圾收集器。在 Server 模式下,主要有两个用途:

          1. 在 JDK1.5 之前版本中与新生代的 Parallel Scavenge 收集器搭配使用。
          1. 作为年老代中使用 CMS 收集器的后备垃圾收集方案。新生代 Parallel Scavenge 收集器与 ParNew 收集器工作原理类似,都是多线程的收集器,都使 用的是复制算法, 在垃圾收集过程中都需要暂停所有的工作线程。
    • 4.7.5 Parallel Old 收集器(多线程标记整理算法)

      • Parallel Old 收集器是 Parallel Scavenge 的年老代版本,使用多线程的标记-整理算法,在 JDK1.6 才开始提供。在JDK1.6 之前,新生代使用 ParallelScavenge 收集器只能搭配年老代的 Serial Old 收集器,只 能保证新生代的吞吐量优先,无法保证整体的吞吐量,Parallel Old 正是为了在年老代同样提供吞 吐量优先的垃圾收集器,如果系统对吞吐量要求比较高,可以优先考虑新生代 Parallel Scavenge 和年老代 Parallel Old 收集器的搭配策略。
    • 4.7.6 CMS 收集器(多线程标记清除算法)

      • Concurrent mark sweep(CMS)收集器是一种年老代垃圾收集器,其最主要目标是获取最短垃圾 回收停顿时间,和其他年老代使用标记-整理算法不同,它使用多线程的标记-清除算法。最短的垃圾收集停顿时间可以为交互比较高的程序提高用户体验。 CMS 工作机制相比其他的垃圾收集器来说更复杂,整个过程分为以下 4 个阶段:

        • 4.7.6.1 初始标记

          • 只是标记一下 GC Roots 能直接关联的对象,速度很快,仍然需要暂停所有的工作线程
        • 4.7.6.2 并发标记

          • 进行 GC Roots 跟踪的过程,和用户线程一起工作,不需要暂停工作线程。
        • 4.7.6.3 重新标记

          • 为了修正在并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记 记录,仍然需要暂停所有的工作线程
        • 4.7.6.4 并发清除

          • 清除 GC Roots 不可达对象,和用户线程一起工作,不需要暂停工作线程。由于耗时最长的并 发标记和并发清除过程中,垃圾收集线程可以和用户现在一起并发工作, 所以总体上来看 CMS 收集器的内存回收和用户线程是一起并发地执行。
    • 4.7.7 收集器

      • Garbage first 垃圾收集器是目前垃圾收集器理论发展的最前沿成果,相比与 CMS 收集器,G1 收 集器两个最突出的改进是:

          1. 基于标记-整理算法,不产生内存碎片。
          1. 可以非常精确控制停顿时间,在不牺牲吞吐量前提下,实现低停顿垃圾回收。G1 收集器避免全区域垃圾收集,它把堆内存划分为大小固定的几个独立区域,并且跟踪这些区域 的垃圾收集进度,同时在后台维护一个优先级列表,每次根据所允许的收集时间,优先回收垃圾 最多的区域。区域划分和优先 级区域回收机制,确保 G1 收集器可以在有限时间获得最高的垃圾收 集效率

5 JVM 参数详解
  • 5.1 通用 JVM 参数

    • 5.1.1 -server

      • 如果不配置该参数,JVM会根据应用服务器硬件配置自动选择不同模式,server模式启动比较慢,但是运行期速度得到了优化,适合于服务器端运行的JVM
    • 5.1.2 -client

      • 启动比较快,但是运行期相应没有server模式的优化,适合于个人PC的服务开发和测试
    • 5.1.3 -Xmx

      • 设置java heap的最大值,默认是机器物理内存的1/4.这个值决定了最多可用的Java堆内存:分配过少就会在应用中需要大量内存作为缓存或者临时对象时出现OOM(Out Of Memory)的问题:如果分配过大,name就会因PermSize过小而引起的另一种OutOfMemory。所以如何配置还是根据运行过程中的分析和计算来确定,如果不能确定还是采用默认的配置
    • 5.1.4 -Xms

      • 设置Java堆初始化时的大小,默认情况是机器物理内存的1/64.这个主要是根据应该用启动时消耗的资源决定,分配少了申请起来会降低运行速度,分配多了也浪费。
    • 5.1.5 -XX:PermSize

      • 初始化永久内存区域大小。永久内存区域全称是 Permanent Generation space,是指内存的永久保存区域,程序运行期不对 PermGen space 进行清理,所以如果你的 APP 会 LOAD 很多 CLASS 的话,就很可能出现 PermGen space错误。这种错误常见在 web 服务器对 JSP 进行 pre compile 的时候。 如果你的 WEB APP 下用了大量的第三方 jar, 其大小超过了 jvm 默认的 PermSize 大小(4M)那么就会产生此错误信息了。
    • 5.1.6 -XX:MaxPermSize

      • 设置永久内存区域最大大小
    • 5.1.7 -Xmn

      • 直接设置青年代大小。整个 JVM 可用内存大小=青年代大小 + 老年代大小 + 持久代大小 。持久代一般固定大小为 64m,所以增大年轻代后,将会减小老年代大小。此值对系统性能影响较大,Sun 官方推荐配置为整个堆的3/8。按照 Sun 的官方设置比例,则上面的例子中年轻代的大小应该为 2048*3/8=768M
    • 5.1.8 -XX:NewRatio

      • 控制默认的 Young 代的大小,例如,设置-XX:NewRatio=3 意味着 Young 代和老年代的比率是 1:3。换句话说,Eden 和 Survivor 空间总和是整个堆大小的 1/4。
      如图中的实际设置,-XX:NewRatio=2,-Xmx=2048,则年轻代和老年代的分配比例为 1:2,即年轻代的大小为 682M, 而老年代的大小为 1365M。查看实际系统的 jvm 监控结果为:
      内存池名称: Tenured Gen
      Java 虚拟机最初向操作系统请求的内存量: 3,538,944 字节
      Java 虚拟机实际能从操作系统获得的内存量: 1,431,699,456 字节
      Java 虚拟机可从操作系统获得的最大内存量: 1,431,699,456 字节。请注意,并不一定能获得该内存量。
      Java 虚拟机此时使用的内存量: 1,408,650,472 字节
      即:1,408,650,472 字节=1365M,证明了上面的计算是正确的
      
    • 5.1.9 -XX:SurvivorRatio

      • 设置年轻代中 Eden 区与 Survivor 区的大小比值。设置为 4,则两个 Survivor 区与一个 Eden 区的比值为 2:4,一个 Survivor 区占整个年轻代的 1/6。越大的 survivor 空间可以允许短期对象尽量在年青代消亡;如果 Survivor 空间太小,Copying 收集将直接将其转移到老年代中,这将加快老年代的空间使用速度,引发频繁的完全垃圾回收【SurvivorRatio 的值设为 3,Xmn 为 768M,则每个 Survivor 空间的大小为 768M/5=153.6M。】
    • 5.1.10 -XX:NewSize

      • 为了实现更好的性能,您应该对包含短期存活对象的池的大小进行设置,以使该池中的对象的存活时间不会超过一个垃圾回收循环。新生成的池的大小由 NewSize 和 MaxNewSize 参数确定。通过这个选项可以设置 Java 新对象生产堆内存。在通常情况下这个选项的数值为 1024 的整数倍并且大于 1MB。这个值的取值规则为,一般情况下这个值-XX:NewSize 是最大堆内存(maximum heap size)的四分之一。增加这个选项值的大小是为了增大较大数量的短生命周期对象。增加 Java 新对象生产堆内存相当于增加了处理器的数目。并且可以并行地分配内存,但是请注意内存的垃圾回收却是不可以并行处理的。作用跟-XX:NewRatio 相似, -XX:NewRatio 是设置比例而-XX:NewSize是设置精确的数值。
    • 5.1.11 -XX:MaxNewSize

      • 通过这个选项可以设置最大 Java 新对象生产堆内存。通常情况下这个选项的数值为 1 024 的整数倍并且大于1MB,其功用与上面的设置新对象生产堆内存-XX:NewSize 相同。一般要将 NewSize 和 MaxNewSize 设成一致。
    • 5.1.12 -XX:MaxTenuringThreshold

      • 设置垃圾最大年龄。如果设置为 0 的话,则年轻代对象不经过 Survivor 区,直接进入老年代。对于老年代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在 Survivor 区进行多次复制,这样可以增加对象在年轻代的存活时间,增加在年轻代即被回收的概率【-XX:MaxTenuringThreshold 参数被设置成 5,表示对象会在 Survivor 区进行 5 次复制后如果还没有被回收才会被复制到老年代】
    • 5.1.13 -XX:GCTimeRatio

      • 设置垃圾回收时间占程序运行时间的百分比。该参数设置为 n 的话,则垃圾回收时间占程序运行时间百分比的公式为 1/(1+n) ,如果 n=19 表示 java 可以用 5%的时间来做垃圾回收,1/(1+19)=1/20=5%。
    • 5.1.14 -XX:TargetsurvivorRatio

      • 该值是一个百分比,控制允许使用的救助空间的比例,默认值是 50。该参数设置较大的话可提高对 survivor 空间的使用率。当较大的堆栈使用较低的 SurvivorRatio 时,应增加该值到 80 至 90,以更好利用救助空间。
    • 5.1.15 -Xss

      • 设置每个线程的堆栈大小,根据应用的线程所需内存大小进行调整,在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000 左右。当这个选项被设置的较大(>2MB)时将会在很大程度上降低系统的性能。因此在设置这个值时应该格外小心,调整后要注意观察系统的性能,不断调整以期达到最优。JDK5.0 以后每个线程堆栈大小为 1M,以前每个线程堆栈大小为 256K。
    • 5.1.16 -Xnoclassgc

      • 这个选项用来取消系统对特定类的垃圾回收。它可以防止当这个类的所有引用丢失之后,这个类仍被引用时不会再一次被重新装载,因此这个选项将增大系统堆内存的空间。禁用类垃圾回收,性能会高一点;
  • 5.2 串行收集器参数

    • 5.2.1 -XX:+UseSerialGC:

      • 设置串行收集器
  • 5.3 并行收集器参数

    • 5.3.1 -XX:+UseParallelGC:

      • 选择垃圾收集器为并行收集器,此配置仅对年轻代有效,即上述配置下,年轻代使用并行收集,而老年代仍旧使用串行收集。采用了多线程并行管理和回收垃圾对象,提高了回收效率,提高了服务器的吞吐量,适合于多处理器的服务器。
    • 5.3.2 -XX:ParallelGCThreads

      • 配置并行收集器的线程数,即:同时多少个线程一起进行垃圾回收。此值最好配置与处理器数目相等。
    • 5.3.3 -XX:+UseParallelOldGC:

      • 采用对于老年代并发收集的策略,可以提高收集效率。JDK6.0 支持对老年代并行收集。
    • 5.3.4 -XX:MaxGCPauseMillis

      • 设置每次年轻代并行收集最大暂停时间,如果无法满足此时间,JVM 会自动调整年轻代大小以满足此值。
    • 5.3.5 -XX:+UseAdaptiveSizePolicy

      • 设置此选项后,并行收集器会自动选择年轻代区大小和相应的 Survivor 区比例,以达到目标系统规定的最低响应时间或者收集频率等,此值建议使用并行收集器时,一直打开。
  • 5.4 并发收集器参数

    • 5.4.1 -XX:+UseConcMarkSweepGC

      • 指定在 老年代 使用 concurrent cmark sweep gc。gc thread 和 app thread 并行 ( 在 init-mark 和 remark 时pause app thread)。app pause 时间较短 , 适合交互性强的系统 , 如 web server。它可以并发执行收集操作,降低应用停止时间,同时它也是并行处理模式,可以有效地利用多处理器的系统的多进程处理。
    • 5.4.2 -XX:+UseParNewGC

      • 指定在 New Generation 使用 parallel collector, 是 UseParallelGC 的 gc 的升级版本 , 有更好的性能或者优点 , 可以和 CMS gc 一起使用
    • 5.4.3 -XX:+UseCMSCompactAtFullCollection:

      • 打开对老年代的压缩。可能会影响性能,但是可以消除碎片,在 FULL GC 的时候, 压缩内存, CMS 是不会移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

移动内存的, 因此, 这个非常容易产生碎片, 导致内存不够用, 因此, 内存的压缩这个时候就会被启用。 增加这个参数是个好习惯

[外链图片转存中…(img-W5tEhHuY-1715815658160)]
[外链图片转存中…(img-II94l41h-1715815658160)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值