JVM 常用的参数说明与配置指南

文章目录

  • 前言
  • 一、常见的 JVM 参数
    • 1、JVM模式参数
    • 2、堆内存参数配置
      • 2.1 堆内存基础设置
      • 2.2 元空间设置
      • 2.3 新生代配置
      • 2.4 字符串常量池参数设置
      • 2.5 直接内存设置
      • 2.6 堆内存其他设置
    • 3、GC垃圾回收器参数配置
      • 3.1 设置GC垃圾回收器类型参数
      • 3.2 基础通用配置
      • 3.3 Parallel 和 Parallel Old 常用参数配置
      • 3.4 CMS 常用参数配置
      • 3.5 G1 常用参数配置
    • 4、GC 日志打印参数配置
    • 5、dump 日志参数配置
      • 5.1 OutOfMemory 异常时生成 dump 文件
      • 5.2 发生 Full GC 时生成 dump 文件
    • 6、其它参数配置
  • 二、JVM参数应该怎么设置?
    • 1、堆内存的参数设置
      • 1.1 8G内存
        • 1.1.1 堆内存设置:
        • 1.1.2元空间设置:
        • 1.1.3 直接内存设置:
      • 1.2 16G内存
        • 1.2.1 堆内存设置:
        • 1.2.2 元空间设置:
        • 1.2.3 直接内存设置:
    • 2、GC垃圾回收器参数如何设置
      • 2.1 GC垃圾回收器如何选择?
      • 2.2 CMS 垃圾收集器相关设置
      • 2.3 G1 垃圾收集器相关设置
    • 3、GC 日志打印参数、dump 日志参数配置
      • 3.1、GC 日志打印参数配置
      • 3.2、dump 日志参数配置
  • 三、参数模板示例
    • 1、8G 物理内存参数配置
    • 2、16G 物理内存参数配置
  • 总结

前言

在 Java 应用的运行中,合理配置 JVM 参数对于系统的性能优化和稳定运行至关重要。本文详细介绍了常见的 JVM 参数,包括模式参数、堆内存参数、垃圾回收器参数、日志打印参数、dump 日志参数等,并提供了不同内存大小下的参数设置示例和模板,帮助您更好地理解和配置 JVM 参数,以提升 Java 应用的性能和可靠性。

一、常见的 JVM 参数

1、JVM模式参数

-server
设置 JVM 使 Server 模式,特点是启动速度较慢,但运行时性能和内存管理效率很高,适用于生产环境。在具有 64 位能力的 JDK 环境下默认启用该模式。

-client

设置JVM使用Client模式,特点是启动速度比较快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或开发调试;在32位环境下直接运行Java程序默认启用该模式。

2、堆内存参数配置

2.1 堆内存基础设置

-Xms
设置初始值堆内存,默认是物理内存的 1/64,内存的单位可以是 m g,并且不区分大小写。

-Xmx
设置最大堆内存,默认是物理内存的 1/4,内存的单位可以是 m g,并且不区分大小写。

-Xmn
设置年轻代内存大小,默认和老年代 1:2,-XX:NewSize 初始化年轻代大小 -XX:MaxNewSize 最大年轻代大小。

-Xss
设置每个线程的堆栈大小,默认是 1024k,这个是最大内存并不是开启一个线程马上就会消耗这么多内存。

2.2 元空间设置

-XX:MaxMetaspaceSize
设置元空间最大值,默认是 -1,即不限制,或者说只受限于本地内存大小,如果超过这个值会内存溢出。

-XX:MetaspaceSize
指定元空间触发 Fullgc 的初始阈值(元空间无固定初始大小),以字节为单位,默认是 21M,达到该值就会触发 full gc 进行类型卸载,同时收集器会对该值进行调整:如果释放了大量的空间,就适当降低该值;如果释放了很少的空间,那么在不超过 -XX:MaxMetaspaceSize(如果设置了的话)的情况下,适当提高该值。这个跟早期 jdk 版本的 -XX:PermSize 参数意思不一样,-XX:PermSize 代表永久代的初始容量。触发一次元空间 Full GC 后就会重新计算该值,建议设置成和最大内存一致。

2.3 新生代配置

-XX:NewRatio
新生代占用堆比例(如果有配置 -Xmn,那么会以 -Xmn 配置为准)。默认 -XX:NewRatio=2 新生代占 1,老年代占 2,年轻代占整个堆的 1/3。假如 -XX:NewRatio=4 新生代占 1,老年代占 4,年轻代占整个堆的 1/5,NewRatio 值就是设置老年代的占比,剩下的 1 给新生代。

-XX:SurvivorRatio
用来设置新生代中 eden 空间和 from/to 空间的比例。含义:设置为 8 代表 eden 使用 80%的新生代内存,from 和 to 各用 10%,默认为 8。

-XX:-UseAdaptiveSizePolicy
禁用 Survivor 区自适应策略,默认是开启的,如果不关闭这个配置,新生代 eden 区和 s0 s1 区会在 gc 后自动调整大小,如果设置了 -XX:SurvivorRatio 也只有在没有 GC 之前有效,只要 GC 后就会重新动态计算。

2.4 字符串常量池参数设置

-XX:StringTableSize
字符串常量池 hash 桶大小,类似于 HashTable,最小值 1009,默认 60013,不可动态扩容。

2.5 直接内存设置

-XX:MaxDirectMemorySize
设置直接内存大小,NIO(Non-blocking I/O)中通过 ByteBuffer 等对象分配的堆外内存。默认情况下,直接内存的大小可能会与 Java 堆的最大值 (-Xmx) 相同。

2.6 堆内存其他设置

-XX:+AlwaysPreTouch
在调用main函数之前,使用所有可用的内存分页。这个选项可以用来测试长时间运行的系统,所有的内存都已被分配。默认这个选项
是关闭的,也就是不会使用所有的内存分页。

-XX:MaxHeapFreeRatio
扩张堆内存的时机,堆内存使用率大于 70 时扩张堆内存,如果最大堆内存 = 初始堆内存时该参数无效,默认值 70。

-XX:MinHeapFreeRatio
缩小堆内存的时机,堆内存使用率小于 40 时缩减堆内存,如果最大堆内存 = 初始堆内存时该参数无效,默认值 40。

3、GC垃圾回收器参数配置

3.1 设置GC垃圾回收器类型参数

-XX:+UseSerialGC
配置使用 Serial 单线程垃圾收集器,虚拟机运行在 Client 模式下的默认值,新生代使用 Serial ,老年代则使用 SerialOld。

-XX:+UseParNewGC
配置使用 ParNew 垃圾收集器,新生代使用 ParNew ,老年代则使用 Serial Old。

-XX:+UseParallelGC
配置使用 Parallel Scavenge 垃圾收集器,虚拟机运行在 Server 模式下的默认值,新生代使用 Parallel Scavenge ,老年代使用 Parallel Old 收集器。

-XX:+UseParallelOldGC
配置使用 Parallel Old 垃圾收集器,新生代使用 Parallel Scavenge ,老年代使用 Parallel Old 收集器。

-XX:+UseConcMarkSweepGC
配置使用 CMS 垃圾收集器,新生代使用 ParNew ,老年代使用 CMS + Serial Old 收集器。

-XX:+UseG1GC
配置使用 G1 垃圾收集器。

3.2 基础通用配置

-XX:MaxGCPauseMillis
GC 停顿时间,垃圾收集器会尝试用各种手段达到这个时间,比如减小年轻代。

-XX:MaxTenuringThreshold
新生代晋升老年代阈值,默认是 15 ,不同回收算法不同。

-XX:TargetSurvivorRatio
对象动态年龄判断,默认 50% ,当一批对象大小 >= survivor 区的 50%时这批对象会直接放入老年代。

‐XX:PretenureSizeThreshold
默认值是 0 没有限制,大于这个值的参数直接在老年代分配,这样做的目的是避免在 Eden 区和两个 Survivor 区之间发生大量的内存复制。

-XX:+DisableExplicitGC
忽略手动调用 GC,System.gc()的调用就会变成一个空调用,完全不触发 GC 。

-XX:LargePageSizeInBytes
内存页的大小。

-Duser.timezone
设定 GMT 区域,避免 CentOS 坑爹的时区设置。

-XX:+ScavengeBeforeFullGC
FullGC 前执行 MinorGC ,默认是开启的。

3.3 Parallel 和 Parallel Old 常用参数配置

-XX:GCTimeRatio
调整垃圾回收的时间和总时间的占比,公式 1/(1 + ratio) ,ratio 默认是 99,100 分钟运行时间默认不能超过 1 分钟的 GC 时间,ratio 一般设置为 19 。

-XX:MaxGCPauseMillis
GC 最大暂停毫秒数,默认是 200 毫秒,和 -XX:+GCTimeRatio 有冲突,堆内存小回收速度才会快,而 -XX:+GCTimeRatio 需要保证一定时间内 GC 时间不能超过一个临界值需要增加内存才能减小 GC 时间比,需要找到一个两个参数的合理值。

-XX:ParallelGCThreads
设置垃圾回收线程数量,默认是 CUP 内核数量。

3.4 CMS 常用参数配置

-XX:MaxGCPauseMillis
GC 最大暂停毫秒数,默认是 200 毫秒。

-XX:+CMSParallelInitialMarkEnabled
为了加快此阶段处理速度,减少停顿时间,可以开启初始标记并行化。

-XX:ParallelCMSThreads
CMS 并行线程数量,并行线程用于执行 CMS 垃圾回收器的并行阶段,如初始标记阶段和重新标记阶段。默认值为系统的逻辑处理器数量减 1,目的是为了保留一个处理器用于应用程序线程。

-XX:ConcGCThreads
CMS 并发线程数量,并发线程用于执行 CMS 垃圾回收器的并发阶段,如初始标记阶段、并发标记阶段和并发清理阶段。默认值为系统的逻辑处理器数量减 1,目的是为了保留一个处理器用于应用程序线程。

-XX:CMSInitiatingOccupancyFraction
执行 CMS 的内存占比,percent = 80 ,当我的老年代内存达到 80%触发垃圾回收,默认是 92% ,应为 CMS 采用标记清除需要给浮动垃圾(在最后一步并发清除时其它没有被标记的垃圾遗留)预留空间 。

-XX:+UseCMSInitiatingOccupancyOnly
该参数需要配合 XX:CMSInitiatingOccupancyFraction 使用,只使用设定的回收阈值(-XX:CMSInitiatingOccupancyFraction 设定的值),如果不指定,JVM 仅在第一次使用设定值,后续则会自动调整。

-XX:CMSScavengeBeforeRemark
重新标记阶段前提前进行一次新生代 GC,因为重新标记也会判断新生代对象是否引用老年代对象,有些时候新生代对象已经没有被 GC root 对象引用但是还没有 GC 时,重新标记会扫描到新生代对象并且保留新生代对象引用的老年代对象,默认关闭 false 。

-XX:+UseCMSCompactAtFullGollection
执行完 Full GC 后对内存空间进行压缩整理,默认开启。

-XX:CMSFullGCsBeforeCompaction
设置在执行多少次 Full GC 后对内存空间进行压缩整理,默认 0 次,只要触发 Full GC 就会进行内存压缩。

-XX:+CMSClassUnloadingEnabled
垃圾回收时是否同时卸载不用的 class 信息,默认关闭。

3.5 G1 常用参数配置

-XX:G1HeapRegionSize
指定分区大小(1MB ~ 32MB,且必须是 2 的 N 次幂),不设置默认会根据堆大小分配。堆内存为 1G 默认 1024 个 1MB 分区、堆内存为 2G 默认 2048 个 1MB 分区、堆内存为 4G 默认 2048 个 2MB 分区、堆内存为 4G 默认 2048 个 2MB 分区、堆内存为 6G 默认 6144 个 1MB 分区、堆内存为 8G 默认 2048 个 4MB 分区、以此类推。

-XX:MaxGCPauseMillis
目标暂停时间(默认 200ms) 。

-XX:G1NewSizePercent
新生代内存初始空间(默认整堆 5%) 。PS: 因为 JDK 版本问题,在启动时可能会出现 “Error: VM option ‘G1NewSizePercent’ is experimental and must be enabled via -XX:+UnlockExperimentalVMOptions.” 如果出现上述问题,在启动参数中添加 -XX:+UnlockExperimentalVMOptions 即可。

-XX:G1MaxNewSizePercent
新生代内存最大空间 (默认整堆 60%) 。

-XX:TargetSurvivorRatio
Survivor 区的填充容量(默认 50%),Survivor 区域里的一批对象(年龄 1 + 年龄 2 + 年龄 n 的多个 年龄对象)总和超过了 Survivor 区域的 50%,此时就会把年龄 n(含)以上的对象都放入老年代 。

-XX:MaxTenuringThreshold
最大年龄阈值(默认 15) 。

-XX:InitiatingHeapOccupancyPercent
老年代占用空间达到整堆内存阈值(默认 45%),则执行新生代和老年代的混合收集(MixedGC) 。

-XX:G1MixedGCLiveThresholdPercent
region 中的存活对象低于这个值时才会回收该 region,如果超过这个值,存活对象过多,回收的的意义不大(默认 65%)。

-XX:G1MixedGCCountTarget
在一次回收过程中指定做几次筛选回收(默认 8 次),在最后一个筛选回收阶段可以回收一会,然后暂停回收,恢复系统运行,一会再开始回收,这样可以让系统不至于单次停顿时间过长。

-XX:G1HeapWastePercent
gc 过程中空出来的 region 是否充足阈值,在混合回收的时候,对 Region 回收都是基于复制算法进行的,都是把要回收的 Region 里的存活对象放入其他 Region,然后这个 Region 中的垃圾对象全部清理掉,这样的话在回收过程就会不断空出来新的 Region,一旦空闲出来的 Region 数量达到了堆内存的 5%,此时就会立即停止混合回收,意味着本次混合回收就结束了(默认 5%)。

4、GC 日志打印参数配置

-Xloggc
设置日志目录和日志名称。

示例;

-Xloggc:/data/logs/gc.log

-XX:+UseGCLogFileRotation
开启滚动生成日志,默认关闭。

-XX:NumberOfGCLogFiles
滚动 GC 日志文件数,默认 0 不滚动,保留最多 5 个日志文件。

-XX:GCLogFileSize
GC 文件滚动大小,需开启 UseGCLogFileRotation,每个文件最大为 20MB 。

-XX:+PrintHeapAtGC
在进行 GC 的前后打印出堆的信息。

-XX:+PrintTenuringDistribution
打印新生代晋升详情。

-XX:+PrintStringTableStatistics
打印字符串常量池堆信息。

-verbose:gc
打印 GC 信息。

-XX:+PrintGCDetails
打印 GC 详细信息 。

-XX:+PrintGCTimeStamps
输出 GC 的时间戳(以基准时间的形式)。

-XX:+PrintGCDateStamps
输出 GC 的时间戳(以日期的形式,如 2013 - 05 - 04T21:53:59.234 + 0800)。

-XX:+PrintCommandLineFlags
打印当前 JVM 参数信息,建议在每个程序中都添加上。

-XX:+PrintGCCause
产生 GC 的原因(默认开启)。

5、dump 日志参数配置

5.1 OutOfMemory 异常时生成 dump 文件

-XX:+HeapDumpOnOutOfMemoryError
默认关闭,可以通过 jinfo - flag [+|-]HeapDumpOnOutOfMemoryError < pid > 或 jinfo - flag HeapDumpOnOutOfMemoryError = < value > < pid > 来动态开启或设置值。

-XX:HeapDumpPath
设置文件存储路径,当 HeapDumpOnOutOfMemoryError 开启的时候,dump 文件的保存路径,默认为工作目录下的,可以通过配置指定保存路径。

XX:HeapDumpPath=/data/dump/jvm.hprof

5.2 发生 Full GC 时生成 dump 文件

不推荐开启会增加整体停顿时间。

-XX:+HeapDumpBeforeFullGC
在 Full GC 前 dump 。

-XX:+HeapDumpAfterFullGC
在 Full GC 后 dump 。

-XX:HeapDumpPath
设置 Dump 保存的路径。

-XX:HeapDumpPath=/data/dump/jvm.hprof

6、其它参数配置

-XX:ErrorFile
JVM 自身故障导致进程奔溃时,会有一个日志文件生成,它包含了导致 crash 的重要信息,通过分析文件来查找 crash 原因。

-XX:ErrorFile=/data/logs/error.log

-XX:-OmitStackTraceInFastThrow
JDK1.6 开始,默认 server 模式下开启了这个参数,意为当 jvm 检测到程序在重复抛一个异常,在执行若干次后会将异常吞掉,这里的若干次在 jdk1.7 测得是 20707。即执行 20707 次后,stackTrace 长度会为 0。有时这不利于我们排错,通过指定 OmitStackTraceInFastThrow,可禁用这功能。

二、JVM参数应该怎么设置?

那么JVM参数应该怎么设置呢?首先,几个关键的堆内存的参数是需要设置的。其次,需要选择合适的GC垃圾回收器,并设置相应的GC垃圾回收器参数。最后,为了监控系统的运行状态以及在系统发生异常的时候方便定位问题,所以GC 日志打印参数、dump 日志参数也是需要配置。接下来我们看看这几块参数应该如何配置

1、堆内存的参数设置

主要是根据服务器的内存大小来配置的。这里按照内存8G和16G给出配置

1.1 8G内存

1.1.1 堆内存设置:
  • -Xms4g:设置初始堆内存为 4G。

  • -Xmx4g:设置最大堆内存为 4G。

  • -Xmn2g:设置年轻代内存为 2G。

  • -Xss1m:设置每个线程的堆栈大小为 1M。

  • -XX:+AlwaysPreTouch:在 JVM 初始化时预先分配所有内存,以减少运行时的性能开销。

1.1.2元空间设置:
  • -XX:MetaspaceSize=128m:设置元空间的初始大小为 128M。

  • -XX:MaxMetaspaceSize=256m:设置元空间的最大大小为 256M。

1.1.3 直接内存设置:
  • -XX:MaxDirectMemorySize=1024m:设置直接内存大小为 1024M(1G)。

1.2 16G内存

1.2.1 堆内存设置:
  • -Xms4g:设置初始堆内存为 8G。

  • -Xmx4g:设置最大堆内存为 8G。

1.2.2 元空间设置:
  • -XX:MetaspaceSize=128m:设置元空间的初始大小为 128M。

  • -XX:MaxMetaspaceSize=256m:设置元空间的最大大小为 256M。

1.2.3 直接内存设置:
  • -XX:MaxDirectMemorySize=1024m:设置直接内存大小为 1024M(1G)。

2、GC垃圾回收器参数如何设置

2.1 GC垃圾回收器如何选择?

那么GC垃圾回收器应该怎么选择呢?其实主要就是以下几点:

首先是CPU核心数

如果服务器是单核、双核cpu的话,不适合并发类垃圾收集器,线程频繁来回切换也会比较耗时间,还不如串行垃圾收集器效率高。这时直接设置-XX:+UseSerialGC,这样配置就使用 Serial 单线程垃圾收集器。

其次的话,需要看服务器的内存大小和JDK的版本

因为G1 的最小堆内存 6个G才能能稳定运行,因此对cpu的要求最少是4核8G,JDK7及更低版本同等环境下 G1不够完善。所以JDK8及更高版本同等环境下只要内存够大(最少8G)优先使用G1,如果不符合的话则选择CMS (最少也需要内存4G)。

2.2 CMS 垃圾收集器相关设置

  • -XX:+UseConcMarkSweepGC:选择 CMS 垃圾收集器。

  • -XX:+DisableExplicitGC:禁止应用程序显式触发垃圾回收。

  • -XX:+CMSParallelRemarkEnabled:启用 CMS 垃圾收集器的并行备注阶段。

  • -XX:CMSInitiatingOccupancyFraction=70:当老年代空间被占用 70%时,尝试执行 CMS 垃圾收集。

  • -XX:+UseCMSInitiatingOccupancyOnly:仅根据初始化占用阈值来启动 CMS 垃圾回收周期。

  • -XX:+UseCMSCompactAtFullCollection:在 CMS 垃圾收集的完整收集阶段进行内存压缩。

  • -XX:CMSFullGCsBeforeCompaction=10:每进行 10 次完整的 CMS 垃圾收集后进行一次内存压缩。

2.3 G1 垃圾收集器相关设置

  • -XX:+UseG1GC:选择 G1 垃圾收集器。
  • -XX:MaxGCPauseMillis=100:设置最大垃圾回收暂停时间为 100 毫秒。
  • -XX:InitiatingHeapOccupancyPercent=50:当堆内存占用达到 50%时,触发 G1 垃圾回收。

3、GC 日志打印参数、dump 日志参数配置

GC 日志打印参数、dump 日志参数的配置比较固定,按照以下配置即可

3.1、GC 日志打印参数配置

-XX:+PrintCommandLineFlags:打印当前 JVM 的命令行参数。

  • -verbose:gc:启用垃圾回收的详细输出。

  • -Xloggc:gc.log:指定垃圾回收日志的输出文件为 gc.log

  • -XX:GCLogFileSize=50M:设置垃圾回收日志文件的大小为 50M。

  • -XX:+PrintGCDetails:打印垃圾回收的详细信息。

  • -XX:+PrintGCDateStamps:打印垃圾回收的日期戳。

  • -XX:+PrintGCTimeStamps:打印垃圾回收的时间戳。

  • -XX:NativeMemoryTracking=detail:详细跟踪本地内存的使用情况。

3.2、dump 日志参数配置

  • -XX:+HeapDumpOnOutOfMemoryError:在发生内存溢出错误时生成堆转储文件。

  • -XX:HeapDumpPath=./:指定堆转储文件的保存路径为当前目录。

三、参数模板示例

接下来我会按照存储大小给出两个配置:一个8G(cms)、一个16G(G1)的JVM参数配置模板。

1、8G 物理内存参数配置

-XX:+PrintCommandLineFlags
-Xms4g
-Xmx4g
-Xmn2g
-Xss1m
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m
-XX:SurvivorRatio=8
-XX:MaxDirectMemorySize=1024m
-XX:+UseConcMarkSweepGC
-XX:+DisableExplicitGC
-XX:+CMSParallelRemarkEnabled
-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+UseCMSCompactAtFullCollection
-XX:CMSFullGCsBeforeCompaction=10
-XX:+AlwaysPreTouch
-XX:+HeapDumpOnOutOfMemoryError
-verbose:gc
-Xloggc:gc.log
-XX:GCLogFileSize=50M
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-XX:NativeMemoryTracking=detail

解释
此配置适用于 8G 物理内存的情况,选择了 CMS 垃圾收集器,并对堆内存、元空间、直接内存进行了合理的分配和设置。通过各种参数来优化垃圾回收的行为,如设置老年代的占用阈值触发垃圾回收、进行内存压缩以减少碎片等。同时,配置了详细的日志输出和内存跟踪,以便在出现问题时进行分析和诊断。

2、16G 物理内存参数配置

-XX:+PrintCommandLineFlags
-Xms8g
-Xmx8g
-XX:MaxDirectMemorySize=1g
-Xss512k
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=256m
-XX:+UseG1GC
-XX:MaxGCPauseMillis=100
-XX:InitiatingHeapOccupancyPercent=50
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-XX:+PrintGCTimeStamps
-Xloggc:gc.log
-verbose:gc
-XX:GCLogFileSize=50M
-XX:NativeMemoryTracking=summary

解释:
对于 16G 物理内存,此配置同样对堆内存、元空间和直接内存进行了设定。选择 G1 垃圾收集器,并设置了相关的参数,如最大暂停时间和堆占用触发回收的阈值。通过生成堆转储文件和详细的日志输出,便于在需要时进行问题排查和性能分析。本地内存的跟踪方式为摘要形式。

总结

本文全面涵盖了 JVM 参数的各个方面,从模式选择到具体的堆内存、垃圾回收器、日志打印和 dump 日志等参数的配置。针对不同的内存大小(8G 和 16G)给出了详细的参数设置示例,并对每个参数的作用和配置原则进行了说明。同时,还介绍了如何根据服务器的 CPU 核心数、内存大小和 JDK 版本选择合适的垃圾回收器,并给出了 CMS 和 G1 垃圾回收器的相关参数设置。通过这些内容,希望能为您在配置 JVM 参数时提供全面且实用的指导。

  • 52
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

知北游z

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

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

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

打赏作者

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

抵扣说明:

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

余额充值