万字长文教你看懂java G1垃圾回收日志

jvm:jvm GC日志解析:G1日志解析 1、背景简介 1.1、应用背景介绍 1)业务特点:流量高峰都集中在白天,凌晨流量很低。 2)应用特点: 对外提供了很多核心业务接口,早6点之后,流量逐渐增加。 凌晨会通过自动化调度,跑一些数据处理任务,主要都是核心业务数据的缓存预热【从DB(mysql/es)读取,写入到redis】。 1.2、jdk版本(openjdk) 由于oracle声明将针对企业用户对于JDK 8 u191之后的版本需要付费购买商业许可。所以公司统一都切换到了openjdk,目前应用的版本是:openjdk 1.8.0_272- 阅读详情
AI摘要

本文详细介绍如何在IDEA中配置G1GC日志参数,解析G1垃圾收集器的新生代收集、并发垃圾收集及FullGC日志,帮助理解G1GC行为,优化JVM。

写在前面: 我是「境里婆娑」。我还是从前那个少年,没有一丝丝改变,时间只不过是考验,种在心中信念丝毫未减,眼前这个少年,还是最初那张脸,面前再多艰险不退却。
写博客的目的就是分享给大家一起学习交流,如果您对 Java感兴趣,可以关注我,我们一起学习。

提起看GC日志大部分同学可能都会皱起眉头不知道如何看、什么时候看以及GC日志如何帮助我们调优JVM等。本篇文章将讲解主流垃圾回收器G1,目前Java官方推荐使用G1,所以学看G1垃圾回收日志迫在眉睫。
在这里插入图片描述

在学习查看G1 GC日志之前,如果对G1不是很了解,可以看这篇文章,讲的非常详细。

传送门: G1垃圾收集器简介

G1的日志参数分为等级递增的三块,这篇文章将会分别介绍每一部分参数的作用和调优时候使用的场景。

一、如何在idea打印G1日志

在idea中配置启动参数
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseG1GC
在这里插入图片描述

二、G1基础参数

如果你要在生产环境中使用G1 GC,下面这些跟日志相关的参数是必备的,有了这些参数,你才能排查基本的垃圾回收问题。

-Xloggc:/path/to/gc.log写入GC日志的路径
-XX:+UseGCLogFileRotation启用GC日志文件轮换
-XX:NumberOfGCLogFiles = 要保留的旋转GC日志文件数
-XX:GCLogFileSize = 每个GC日志文件的大小以启动轮换
-XX:+ PrintGCDetial详细的GC日志
-XX:+ PrintGCDateStamps每次GC时会打印程序启动后至GC发生的时间戳
-XX:+ PrintGCApplicationStoppedTimeGC期间应用程序停止的时间
-XX:+ PrintGCApplicationConcurrentTime应用程序在GC之间运行的时间
-XX:-PrintCommandLineFlags在GC日志中打印所有命令行标志
-XX:MaxGCPauseMillis=n设置最大GC停顿时间(GC pause time)指标(target). 这是一个软性指标(soft goal), JVM 会尽量去达成这个目标.
XX:InitiatingHeapOccupancyPercent=n启动并发GC周期时的堆内存占用百分比. G1之类的垃圾收集器用它来触发并发GC周期,基于整个堆的使用率,而不只是某一代内存的使用比. 值为 0 则表示"一直执行GC循环". 默认值为 45.
-XX:NewRatio=n新生代与老生代(new/old generation)的大小比例(Ratio). 默认值为 2.
-XX:SurvivorRatio=neden/survivor 空间大小的比例(Ratio). 默认值为 8.
-XX:MaxTenuringThreshold=n提升年老代的最大临界值(tenuring threshold). 默认值为 15.
-XX:G1ReservePercent=n设置堆内存保留为假天花板的总量,以降低提升失败的可能性. 默认值是 10.
-XX:G1HeapRegionSize=n使用G1时Java堆会被分为大小统一的的区(region)。此参数可以指定每个heap区的大小. 默认值将根据 heap size 算出最优解. 最小值为 1Mb, 最大值为 32Mb.

使用-XX:GCLogFileSize设置合适的GC日志文件大小,使用-XX:NumberOfGCLogFiles设置要保留的GC日志文件个数,使用-Xloggc:/path/to/gc.log设置GC日志文件的位置,通过上面三个参数保留应用在运行过程中的GC日志信息,我建议最少保留一个星期的GC日志,这样应用的运行时信息足够多的,方便排查问题。

三、G1新生代收集

和其他垃圾收集器一样,G1也使用-XX:PrintGCDetails打印出详细的垃圾收集日志,下面是新生代收集的标准流程,我在这里将它分成了6个步骤:

     1	2020-04-25T15:36:17.135+0800: [GC pause (G1 Evacuation Pause) (young), 0.0044414 secs]
     2	   [Parallel Time: 3.4 ms, GC Workers: 4]
	      [GC Worker Start (ms): Min: 8782.3, Avg: 8783.2, Max: 8785.7, Diff: 3.3]
	      [Ext Root Scanning (ms): Min: 0.0, Avg: 0.4, Max: 0.6, Diff: 0.6, Sum: 1.6]
	      [Update RS (ms): Min: 0.0, Avg: 1.0, Max: 1.5, Diff: 1.5, Sum: 4.1]
		 [Processed Buffers: Min: 0, Avg: 2.5, Max: 6, Diff: 6, Sum: 10]
	      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
	      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
	      [Object Copy (ms): Min: 0.0, Avg: 1.0, Max: 1.3, Diff: 1.3, Sum: 3.9]
	      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.2]
	      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.1]
	      [GC Worker Total (ms): Min: 0.0, Avg: 2.5, Max: 3.3, Diff: 3.3, Sum: 9.9]
	      [GC Worker End (ms): Min: 8785.7, Avg: 8785.7, Max: 8785.7, Diff: 0.0]
	3  [Code Root Fixup: 0.0 ms]
	   [Code Root Migration: 0.0 ms]
	   [Clear CT: 0.0 ms]
	4   [Other: 1.0 ms]
	      [Choose CSet: 0.0 ms]
	      [Ref Proc: 0.6 ms]
	      [Ref Enq: 0.0 ms]
	      [Free CSet: 0.0 ms]
	5   [Eden: 4096.0K(4096.0K)->0.0B(3072.0K) Survivors: 1024.0K->1024.0K Heap: 23.9M(28.0M)->20.4M(28.0M)]
	6 [Times: user=0.00 sys=0.02, real=0.01 secs] 
1、 四个关键信息
  • 新生代垃圾收集发生的时间——2020-04-25T15:36:17.135+0800,通过设置-XX:+PrintGCDateStamps参数可以打印出这个时间;
  • 这次收集的类型——新生代收集,只回收Eden分区
  • 这次收集花费的时间——0.0044414 secs,即4ms
2、 列出了新生代收集中并行收集的详细过程
  • Parallel Time:并行收集任务在运行过程中引发的STW(Stop The World)时间,从新生代垃圾收集开始到最后一个任务结束,共花费3.4 ms
  • GC Workers:有4个线程负责垃圾收集,通过参数-XX:ParallelGCThreads设置,这个参数的值的设置,跟CPU有关,如果物理CPU支持的线程个数小于8,则最多设置为8;如果物理CPU支持的线程个数大于8,则默认值为number * 5/8
  • GC Worker Start:第一个垃圾收集线程开始工作时JVM启动后经过的时间(min);最后一个垃圾收集线程开始工作时JVM启动后经过的时间(max);diff表示min和max之间的差值。理想情况下,你希望他们几乎是同时开始,即diff趋近于0。
  • Ext Root Scanning:扫描root集合(线程栈、JNI、全局变量、系统表等等)花费的时间,扫描root集合是垃圾收集的起点,尝试找到是否有root集合中的节点指向当前的收集集合(CSet)
  • Update RS(Remembered Set or RSet):每个分区都有自己的RSet,用来记录其他分区指向当前分区的指针,如果RSet有更新,G1中会有一个post-write barrier管理跨分区的引用——新的被引用的card会被标记为dirty,并放入一个日志缓冲区,如果这个日志缓冲区满了会被加入到一个全局的缓冲区,在JVM运行的过程中还有线程在并发处理这个全局日志缓冲区的dirty card。Update RS表示允许垃圾收集线程处理本次垃圾收集开始前没有处理好的日志缓冲区,这可以确保当前分区的RSet是最新的。
  • Processed Buffers,这表示在Update RS这个过程中处理多少个日志缓冲区。
  • Scan RS:扫描每个新生代分区的RSet,找出有多少指向当前分区的引用来自CSet。
  • Code Root Scanning:扫描代码中的root节点(局部变量)花费的时间
  • Object Copy:在疏散暂停期间,所有在CSet中的分区必须被转移疏散,Object Copy就负责将当前分区中存活的对象拷贝到新的分区。
  • Termination:当一个垃圾收集线程完成任务时,它就会进入一个临界区,并尝试帮助其他垃圾线程完成任务(steal outstanding tasks),min表示该垃圾收集线程什么时候尝试terminatie,max表示该垃圾收集回收线程什么时候真正terminated。
  • Termination Attempts:如果一个垃圾收集线程成功盗取了其他线程的任务,那么它会再次盗取更多的任务或再次尝试terminate,每次重新terminate的时候,这个数值就会增加。
  • GC Worker Other:垃圾收集线程在完成其他任务的时间
  • GC Worker Total:展示每个垃圾收集线程的最小、最大、平均、差值和总共时间。
  • GC Worker End:min表示最早结束的垃圾收集线程结束时该JVM启动后的时间;max表示最晚结束的垃圾收集线程结束时该JVM启动后的时间。理想情况下,你希望它们快速结束,并且最好是同一时间结束。
3、列出了新生代GC中的一些任务:
  • Code Root Fixup :释放用于管理并行垃圾收集活动的数据结构,应该接近于0,该步骤是线性执行的;
  • Code Root Purge:清理更多的数据结构,应该很快,耗时接近于0,也是线性执行。
  • Clear CT:清理card table
4、包含一些扩展功能
  • Choose CSet:选择要进行回收的分区放入CSet(G1选择的标准是垃圾最多的分区优先,也就是存活对象率最低的分区优先)
  • Ref Proc:处理Java中的各种引用——soft、weak、final、phantom、JNI等等。
  • Ref Enq:遍历所有的引用,将不能回收的放入pending列表
  • Redirty Card:在回收过程中被修改的card将会被重置为dirty
  • Humongous Register:JDK8u60提供了一个特性,巨型对象可以在新生代收集的时候被回收——通过G1ReclaimDeadHumongousObjectsAtYoungGC设置,默认为true。
  • Humongous Reclaim:做下列任务的时间:确保巨型对象可以被回收、释放该巨型对象所占的分区,重置分区类型,并将分区还到free列表,并且更新空闲空间大小。
  • Free CSet:将要释放的分区还回到free列表。
5、展示了不同代的大小变化,以及堆大小的自适应调整。

Eden:4096.0K(4096.0K)->0.0B(3072.0K):(1)当前新生代收集触发的原因是Eden空间满了,分配了4096K,使用了4096K;(2)所有的Eden分区都被疏散处理了,在新生代结束后Eden分区的使用大小成为了0.0B;(3)Eden分区的大小缩小为3072K
Survivors:1024.0K->1024.0K:由于年轻代分区的无回收处理,survivor的空间不变。
Heap: 23.9M(28.0M)->20.4M(28.0M):(1)在本次垃圾收集活动开始的时候,堆空间整体使用量是23.9M,堆空间的最大值是28.0M;(2)在本次垃圾收集结束后,堆空间的使用量是20.4M,最大值保持不变。

6、第6点展示了本次新生代垃圾收集的时间
  • user=0.8:垃圾收集线程在新生代垃圾收集过程中消耗的CPU时间,这个时间跟垃圾收集线程的个数有关,可能会比real time大很多;
  • sys=0.0:内核态线程消耗的CPU时间
  • real=0.03:本次垃圾收集真正消耗的时间;
四、并发垃圾收集

G1的第二种收集活动是并发垃圾收集,并发垃圾收集的触发条件有很多,但是做的工作都相同,它的日志所示:

1 2020-04-25T15:36:17.590+0800: [GC pause (G1 Evacuation Pause) (young),(initial-mark), 0.0043944 secs]
2 2020-04-25T15:36:17.590+0800: [GC concurrent-root-region-scan-start]
  2020-04-25T15:36:17.594+0800: [GC concurrent-root-region-scan-end, 0.0043944 secs]
3 2020-04-25T15:36:17.594+0800: [GC concurrent-mark-start]
  2020-04-25T15:36:17.640+0800: [GC concurrent-mark-end, 0.0460160 secs]
4 2020-04-25T15:36:17.640+0800: [GC remark [GC ref-proc, 0.0028598 secs], 0.0130111 secs]
 [Times: user=0.00 sys=0.00, real=0.01 secs] 
5 2020-04-25T15:36:17.654+0800: [GC cleanup 18M->18M(56M), 0.0001847 secs]
 [Times: user=0.00 sys=0.00, real=0.00 secs] 
6 2020-04-25T15:36:17.890+0800: [GC concurent-cleanup-stat]
  2020-04-25T15:36:17.904+0800: [GC concurrent-cleanup-end, 0.0001847 secs]
1、标志着并发垃圾收集阶段的开始
  • GC pause(G1 Evacuation Pause)(young)(initial-mark):为了充分利用STW的机会来trace所有可达(存活)的对象,initial-mark阶段是作为新生代垃圾收集中的一部分存在的(搭便车)。initial-mark设置了两个TAMS(top-at-mark-start)变量,用来区分存活的对象和在并发标记阶段新分配的对象。在TAMS之前的所有对象,在当前周期内都会被视作存活的。
2、表示第并发标记阶段做的第一个事情:根分区扫描
  • GC concurrent-root-region-scan-start:根分区扫描开始,根分区扫描主要扫描的是新的survivor分区,找到这些分区内的对象指向当前分区的引用,如果发现有引用,则做个记录;
  • GC concurrent-root-region-scan-end:根分区扫描结束,耗时0.0460160 secs
3、表示并发标记阶段
  • GC Concurrent-mark-start:并发标记阶段开始。(1)并发标记阶段的线程是跟应用线程一起运行的,不会STW,所以称为并发;并发标记阶段的垃圾收集线程,默认值是Parallel Thread个数的25%,这个值也可以用参数-XX:ConcGCThreads设置;(2)trace整个堆,并使用位图标记所有存活的对象,因为在top TAMS之前的对象是隐式存活的,所以这里只需要标记出那些在top TAMS之后、阈值之前的;(3)记录在并发标记阶段的变更,G1这里使用了SATB算法,该算法要求在垃圾收集开始的时候给堆做一个快照,在垃圾收集过程中这个快照是不变的,但实际上肯定有些对象的引用会发生变化,这时候G1使用了pre-write barrier记录这种变更,并将这个记录存放在一个SATB缓冲区中,如果该缓冲区满了就会将它加入到一个全局的缓冲区,同时G1有一个线程在并行得处理这个全局缓冲区;(4)在并发标记过程中,会记录每个分区的存活对象占整个分区的大小的比率;
  • GC Concurrent-mark-end:并发标记阶段结束,耗0.0460160 secs
4、重新标记阶段,会Stop the World
  • Finalize Marking:Finalizer列表里的Finalizer对象处理,耗时0.0130111s;
  • GC ref-proc:引用(soft、weak、final、phantom、JNI等等)处理,耗时 0.0028598s;
    除了前面这几个事情,这个阶段最关键的结果是:绘制出当前并发周期中整个堆的最后面貌,剩余的SATB缓冲区会在这里被处理,所有存活的对象都会被标记;
5、清理阶段,也会Stop the World
  • 计算出最后存活的对象:标记出initial-mark阶段后分配的对象;标记出至少有一个存活对象的分区;
  • 为下一个并发标记阶段做准备,previous和next位图会被清理;
  • 没有存活对象的老年代分区和巨型对象分区会被释放和清理;
  • 处理没有任何存活对象的分区的RSet;
  • 所有的老年代分区会按照自己的存活率(存活对象占整个分区大小的比例)进行排序,为后面的CSet选择过程做准备;
6、并发清理阶段
  • GC concurrent-cleanup-start:并发清理阶段启动。完成第5步剩余的清理工作;将完全清理好的分区加入到二级free列表,等待最终还会到总体的free列表;
  • GC concurrent-cleanup-end:并发清理阶段结束,耗时0.0001847s
五、程序发生Full GC

如果堆内存空间不足以分配新的对象,或者是Metasapce空间使用率达到了设定的阈值,那么就会触发Full GC——你在使用G1的时候应该尽量避免这种情况发生,因为G1的Full Gc是单线程、会Stop The World,代价非常高。Full GC的日志如下所示,从中你可以看出三类信息

  • Full GC的原因,这个图里是Allocation Failure,还有一个常见的原因是Metadata GC Threshold;
  • Full GC发生的频率,每隔几天发生一次Full GC还可以接受,但是每隔1小时发生一次Full GC则不可接受;
  • Full GC的耗时,这张图里的Full GC耗时3s(PS:按照我的经验,实际运行中如果发生Full GC,耗时会比这个多很多)
2020-04-25T18:00:11.267+0800: [Full GC (Allocation Failure)  1520M->918M(1886M), 5.1284574 secs]
   [Eden: 0.0B(93.0M)->0.0B(94.0M) Survivors: 1024.0K->0.0B Heap: 1520.8M(1886.0M)->918.5M(1886.0M)], [Metaspace: 39714K->39714K(1085440K)]
 [Times: user=5.02 sys=0.00, real=5.13 secs] 
2020-04-25T18:00:16.395+0800: [Full GC (Allocation Failure)  918M->916M(1886M), 4.7699272 secs]
   [Eden: 0.0B(94.0M)->0.0B(94.0M) Survivors: 0.0B->0.0B Heap: 918.5M(1886.0M)->916.1M(1886.0M)], [Metaspace: 39714K->39488K(1085440K)]
 [Times: user=4.73 sys=0.00, real=4.77 secs] 

基础配置参数中,我这里还想介绍两个:-XX:+PrintGCApplicationStoppedTime和-XX:+PrintGCApplicationConcurrentTime,这两个参数也可以为你提供有用的信息,如下所示

1 2020-04-25T18:00:11.266+0800: Total time for which application threads were stopped: 0.0024315 seconds
2 2020-04-25T18:00:11.266+0800: Application time: 0.0000549 seconds

1 、记录了应用线程在安全点被暂停的总时间(也就是STW的总时间)
2、 记录了在两个安全点之间应用线程运行的时间

本篇文章参考:Collecting and reading G1 garbage collector logs


由于本人水平有限,难免有不足,恳请各位大佬不吝赐教!

JVM性能分析 —— G1 日志分析 文章目录日志级别-XX:+PrintGC(简洁版)-XX:+PrintGCDetails(详细版)-XX:G1LogLevel=finest(非常详细版)YGC 日志并发标记日志Mixed GC 日志Full GC 日志 日志级别 JVM 日志级别中的 fine、finer 和 finest 这三个级别 fine:JVM 配置参数为 -XX:G1LogLevel=fine 或使用 -XX:+PrintGC。 用于输出一些常规性的信息,不会产生太多的日志输出。 finer:JVM 配置参数为 -XX: 阅读详情

相关推荐

JVM虚拟机(十二)ParallelGC、CMS、G1垃圾收集器的 GC 日志解析

JVM虚拟机(十二)ParallelGC、CMS、G1垃圾收集器的 GC 日志解析

ACGkaka的博客 2628

深入理解G1的GC日志

G1模式下总计有3中日志级别,分别被称为:fine,finer,finest。 fine:fine模式打开方式是-verbose:gc,等价于-XX:+PrintGC。 finer:推荐,finer模式的打开方式是-XX:+PrintGCDetails。 finest:finest模式打开方式是-XX:+UnlockExperimentalVMOptions -XX:G1LogLevel=fine...

weixin_33951761的博客 1362

万字长文!深入详解Java垃圾回收(GC)机制

一、为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。 二、哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无非就是那些不可能再被任何途径使用的对象。那么如何找到这些对象? 1、引用计数法 这个算法的实现是,给对象中添加一个引用计数器,每当一个地方引用这个对象时,计数器值+1;当引用失效时,计数器值-1。任何时刻计数值为0的对象

weixin_57907028的博客 426

G1原理—G1的GC日志分析解读

使用G1时发生FGC要比使用ParNew + CMS时发生FGC更加困难,并且尝试的次数日志上来看也非常多。FGC的整个过程比较简单粗暴,如果实在无法压缩出空间,就会OOM。东阳马生架构G1原理—7.G1的GC日志分析解读 - 东阳马生架构 - 博客园引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构。

sdgfafg_25的博客 1588

JVM内存模型、垃圾回收与性能调优实战详解

Java虚拟机(JVM)是Java程序运行的基石,其核心在于内存管理与垃圾回收机制。理解JVM内存模型(运行时数据区)是优化程序性能的基础,它精细划分了程序计数器、Java虚拟机栈、本地方法栈、Java堆和方法区等区域,各司其职。垃圾回收(GC)则基于可达性分析算法,自动回收不再使用的对象,以解决内存泄漏和碎片化问题,保障应用稳定运行。其技术价值在于提升资源利用率和系统吞吐量,对于构建高并发、低延迟的中间件(如Netty、Kafka)和大型互联网服务至关重要。在实际应用场景中,面对频繁GC、内存溢出或性能毛

weixin_30591551的博客 431

万字长文!Mysql和Redis数据同步该怎么做?精心整理

什么是 Spring Boot Java (面向对象编程语言)经过30多年的发展,产生了非常多的优秀框架。Spring (为解决企业应用程序开发的复杂性而创建的框架)曾是最受欢迎的Java框架之一, 但随着Node、Ruby、Groovy、PHP等脚本语言的蓬勃发展,使用Spring开发应用就显得繁琐了,因为它使用了大量的XML配置文件,配置繁琐,整合不易,开发和部署效率低下。这时急切需要一-种新的能解决这些问题的快速开发框架,于是Pivotal Software公司在2013开始了Spring Boot的

m0_56301848的博客 404

【JVM】万字长文!深入详解Java垃圾回收(GC)机制

如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分配内存空间而不进行回收。除非内存无限大,我们可以任性的分配而不回收,但是事实并非如此。所以,垃圾回收是必须的。

陈宝子的博客 6705

JAVA新版本特性(10万字长文详解)完全指导手册

这里帮你梳理为何JDK 17将会是一个极为重要的版本以及如何去理解它Java 9 正式发布于 2017 年 9 月 21 日。作为 Java8 之后 3 年半才发布的新版本,Java 9 带来了很多重大的变化。其中最重要的改动是 Java 平台模块系统的引入。除此之外,还有一些新的特性。本文对 Java9 中包含的新特性做了概括性的介绍,可以帮助你快速了解 Java 9作为当今使用最广泛的编程语言之一的 Java 在 2018 年 3 月 21 日发布了第十个大版本。

hao_kkkkk的专栏 1740

万字长文,这回彻底搞懂垃圾回收!

前言 Java 相比 C/C++ 最显著的特点便是引入了自动垃圾回收 (下文统一用 GC 指代自动垃圾回收),它解决了 C/C++ 最令人头疼的内存管理问题,让程序员专注于程序本身,不用关心内存回收这些恼人的问题,这也是 Java 能大行其道的重要原因之一,GC 真正让程序员的生产力得到了释放,但是程序员很难感知到它的存在,这就好比,我们吃完饭后在桌上放下餐盘即走,服务员会替你收拾好这些餐盘,你不...

qq_41490913的博客 155

国产谷歌地球,地形分析秒杀同款地图软件

咱们做地质、林业、水文、水利、电力、GIS、地图、水保、环境的,需要经常用到各种数据,比如影像、地形、矢量、模型等,但目前80%的规划大数据展示都离不开ArcGIS,令人头大的是很多朋友连ArcGIS软件安装起来都费劲。。。 那不会ArcGIS又装不了Google Earth怎么开展工作? 今天推荐大家一款国产免费专业地图浏览下载测量分析神器—图新地球 图新地球,国产三维gis软件。可以查看高清卫星影像地形以及其他很多常用电子地图,对地图需求的掌握远胜过Google Maps,而且上手比国外软件要简单

GISWorld3D的博客 3685

Coding Plan:程序员真实工作的可执行编码决策框架

Coding Plan 是一种面向工程实践的编码决策方法论,它超越传统学习路径,聚焦于代码在真实业务系统中的上下文对齐、影响控制与可演进性保障。其核心在于将模糊的开发直觉转化为可度量、可验证、可协作的日常动作,涵盖目标对齐、上下文锁定、验证闭环、协作契约和演进预留五大锚点。结合2026年AI辅助编码新范式,它强调将大模型作为‘上下文翻译器’而非代码生成器,并通过分钟级工作块、技术债主动发行、可观测性前置等机制,显著提升交付确定性与系统长期健康度。本文详解该框架的底层逻辑与落地实践。

weixin_33326218的博客 438

Java GC:干掉 CMS,G1 才是未来——2 万字深度详解

本文系统剖析了Java垃圾回收器从CMS到G1的演进历程。针对CMS“无刹车跑车”的高停顿与碎片问题,G1以Region化堆布局、RSet与SATB算法实现可预测停顿,通过分代回收与收益优先策略,在保证低停顿的同时提升吞吐量。文章深入解析G1核心机制、调优参数及迁移路径,并结合实战案例说明如何应对大对象、停顿超标等难题。强调:唯有基于日志观测的调优,才能真正驾驭G1,实现稳定高效的生产级应用。

油墨香^-^的博客 340

自动驾驶关键技术(一):时间敏感网络TSN

时间敏感网络TSN的基本概念、协议族介绍和开发流程。

3080

万字长文2024最全Go面经汇总

必看!往期所有大厂面经汇总!总共一万五千多字,总会有你需要的。(本文主要是分享真实的面经,关于这些问题的详解,我们只整理了一部分,文末有他们的详解跳转链接)

王中阳讲编程 4139

通用抓取算法AnyGrasp(Graspnet)——本地部署并测试自定义输入数据

背景:GraspNet在数据采集方面,首先将相机固定到机械臂末端,对同一个场景拍摄256个不同的角度,同时场景中的每个物体都会提前采集好3D模型,之后将其投射到仿真环境中,在仿真环境中,对抓取位姿进行打标签,如此完成数据的采集。在运行官方的测试示例时,使用的是路径下的输入数据,可以分析下。color.png(输入):rgb图像(输出):输出的生成抓取位姿的图像depth.png(输入):和当前rgb图像对应的深度图像(保存格式是单通道uint16)meta.mat。

boss-dog 1329

智能手表 BOM 表与版本管理记录

试产与量产阶段 智能手表 BOM 表与版本管理记录

hoony123的博客 1053

Java内存管理与调优实践--JVM内存管理垃圾收集器上手实践

java内存管理与调优实践--jvm调优垃圾收集器对比上手实践

qq_43460315的博客 993

YOLOv11目标检测模型性能评价指标详解,涉及混淆矩阵、F1-Score、IoU、mAP、参数量、计算量等,一文打尽所有评价指标

本文主要讲解的是计算机视觉网络模型的性能评价指标,这是每一篇论文中都需要展示的内容。熟悉每一个评价指标也能够帮助我们在训练和改进模型过程中,更好的观察模型的变化效果。

Limiiiing的博客 8410

黑马点评背后的JVM江湖:从一个外卖订单看懂Java虚拟机

《从黄焖鸡订单看JVM原理》摘要:本文以黑马点评平台的外卖下单场景为线索,生动解析JVM核心机制。当用户下单黄焖鸡米饭时,JVM启动类加载(如OrderController)、在堆内存创建订单对象、通过栈帧执行方法调用,并触发垃圾回收清理临时对象。文章将JVM比作餐厅后厨:内存模型对应厨房布局(堆/栈/方法区)、GC算法类比垃圾分类、类加载机制如同菜谱管理、JIT编译相当于厨师经验优化。最后针对OOM异常和性能调优给出实战方案,帮助开发者从业务视角理解JVM底层原理,解决实际工程中的内存泄漏、GC频繁等问题

weixin_72753562的博客 1153

机器学习势能(MLPs) 第一章 基础理论与核心概念 第二章 数据生成与训练集构建

密度泛函理论(DFT)作为现代计算材料科学的基石,通过求解Kohn-Sham方程在电子结构层面提供可靠的势能面信息。然而,其计算复杂度随体系电子数呈O(N3) 至O(N4) 增长,对于包含数百个原子的体系,单点计算往往需消耗数小时至数天的计算资源。这一瓶颈严重限制了分子动力学模拟的时间尺度,传统DFT-MD通常仅能覆盖皮秒量级,远不足以观测扩散、相变等慢动力学过程。经验力场通过解析函数形式描述原子间相互作用,实现了经典力学的计算效率,但其参数化过程高度依赖物理直觉与经验调参。

VectorShift的博客 182

基于simulink的BMS系统中电池单体故障隔离与恢复建模

本文介绍了使用Simulink构建BMS电池单体故障诊断与容错控制模型的方法。主要内容包括:1)搭建12串锂电池组模型;2)实现单体故障注入(过压、断线等);3)设计故障诊断与隔离模块(采用Stateflow状态机);4)开发恢复判断逻辑(需满足电压、温度等条件);5)系统监控与仿真设置。文章还提供了工程实践建议,如防环流设计、通信冗余等,并指出进阶方向(多故障处理、AI预警等)。该模型适用于新能源汽车、储能系统的BMS设计,可提高系统可靠性和安全性。

xiaoheshang_123的博客 140

这样调优:让你的 IDEA 快到飞起来,效率真高!2万字详解

本文系统解析IntelliJ IDEA性能下降根源,指出卡顿主因非硬件不足,而是JVM配置、插件负载、项目结构等多层因素所致。从JVM内存与GC优化(如合理设置-Xmx、选用G1/ZGC)、构建加速(增大编译进程堆、启用并行编译)、索引管理(排除无关目录、使用共享索引)、插件精简到代码检查调优,提供可复制的实战配置清单。强调调优需分层推进、逐步验证,最终实现启动快、补全顺、搜索稳的高效开发体验。

油墨香^-^的博客 411

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

虚拟机内存回收异常怎样排查

指标维度调优前(未池化 + 默认 G1)调优后(ByteBuf 池化 + 32M Region)G1 Humongous 分配次数1,420 次/小时0 次/小时Full GC 触发频次12 次/小时0 次老年代 Occupancy 峰值99.8%42.1%P99 GC 停顿时间3,850 ms65 ms高并发 LLM 上下文处理场景中,JVM 内存调优不仅仅是调参,代码层面的对象池化与大对象防护才是治本之策。

alex_goden的博客 5131

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【深夜思考】字节跳动Java三面凉凉,万字长文!

谈起MyBatis,我先提个问:什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录… 而今天咱要聊的就是Alibaba珍藏版mybatis手写文档,刷到的朋友真香警告呀! 拼多多二面:多

m0_56301848的博客 313

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

jdk5-9新特性总结

之前整理过JDK11的一些有用的新特效介绍jdk11特性,这次再整理一期5-9的新特性(下次有机会再整理一次11-17的)

qq_36532060的博客 417

小米后端面试2025:Java并发JVM与分布式实战攻略

后端面试考察的不只是知识记忆,更看重对Java核心机制、并发编程原理、JVM调优方法以及分布式中间件底层逻辑的深度理解。工程实践中,线程池参数联动、HashMap红黑树演进、Redis分布式锁可靠性、MySQL索引优化与分库分表策略,都是技术面试高频考点。面试官通过项目深挖与场景追问,评估候选人在高并发、大流量下的架构决策与问题排查能力。从JVM线上诊断到缓存穿透处理,从Kafka幂等消费到系统设计题框架,掌握基础原理并融入实战经验,才是通过面试的关键。本文以小米后端面试为背景,系统梳理集合框架、并发容器、

weixin_28691741的博客 323
上一篇: 史上最全的SpringBatch学习教程
下一篇: 史上最全的SpringCloud入门学习教程
境里婆娑
境里婆娑 新星创作者: Java技术领域 新星创作者: Java技术领域 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄10年 1万+粉丝 300原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

境里婆娑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值