Java微服务内存占用分析
一、Java 进程中有哪些组件会占用内存?
通过 Native Memory Tracking 可以观察到有以下 JVM 组件。在命令行加上-XX:NativeMemoryTracking=summary,会增加3MB左右内存,损失5%-10%CPU,不宜用于生产环境。
使用 jcmd <pid> VM.native_memory summary scale=MB 可以查看内存分配结果。如果报告"Native memory tracking is not enabled", 是因为该进程起动时命令行没有加上-XX:NativeMemoryTracking=summary参数。
1.1 Java 堆
最显而易见的就是 Java 堆,它是 Java 对象存在的地方。它会占用 -Xmx 参数指定大小的内存。
1.2 线程
线程堆栈也会申请内存。堆栈大小由 -Xss 选项指定,默认每个线程1M,幸运的是情况并非那么糟糕。操作系统会以延迟分配的方式分配内存页面,比如在第一次使用时分配,因此实际使用的内存要低得多,通常每个线程堆栈占用80至200KB。
还有其他 JVM 部件会占用本地内存,但它们在总内存消耗中通常比例不大。
1.3 类加载
类的元数据存储在 Metaspace 堆外区域中,包括方法字节码、符号、常量池、注解等。加载的类越多,使用的元数据就越多。可以通过 -XX:MaxMetaspaceSize(默认无上限)和 -XX:CompressedClassSpaceSize(默认1G)选项控制元数据总大小。
1.4 符号表
JVM 有两个主要的 hashtable:符号表包含名称、签名、标识符等,String 表包含对 interned String 引用。如果 Native Memory Tracking 显示 String 表使用了大量内存,这可能意味着应用程序调用 String.intern 过于频繁。
1.5 垃圾回收器
GC 需要额外的内存进行堆管理,主要用于 GC 自身的结构与算法。这些结构包括 Mark Bitmap、Mark Stack(遍历对象关系图)、Remembered Set(记录 region 之间引用)等等。其中一些可以直接调优,例如 -XX: MarkStackSizeMax 选项,另一些依赖于堆布局。其中 G1 region (-XX:G1HeapRegionSize)占用内存较大,Remembered Set 占用内存较小。
GC 的内存开销因算法而异,其中 -XX:+UseSerialGC 与 -XX:+UseShenandoahGC 的开销最小,而 G1 或 CMS 则会轻松占用大约10%的堆内存。
1.6 代码缓存
代码缓存包含动态生成的代码,JIT 编译生成的方法、解释器以及运行时 stub 代码。代码大小受 -XX:ReservedCodeCacheSize选项限制(默认为240M)。关闭 -XX:-TieredCompilation 可以减少已编译代码的数量,从而减小代码缓存。
1.7 编译器
JIT 编译器本身工作时也需要内存。可以通过关闭 Tiered Compilation 或者 -XX:CICompilerCount 减少编译使用的线程数。
1.8 Direct Buffer
应用程序可以通过 ByteBuffer.allocateDirect 调用直接请求非堆内存。默认的非堆内存大小限制由 -Xmx 选项指定,但也可以使用 -XX:MaxDirectMemorySize 覆盖配置。Direct ByteBuffer 包含在 Native Memory Tracking 输出的 Other 区域,在 JDK 11 之前包含在 Internal 区域。
通过 JMX 可以在 JConsole 或 Java Mission Control 中直接看到 Direct Memory 的使用量:
1.9 Native Library
System.Loadlibrary 加载的 JNI 代码可以不受 JVM 控制分配堆外内存,标准 Java Class Library 也是如此。尤其是未关闭的 Java 资源可能造成本地内存泄漏。典型的例子是 ZipInputStream 和 DirectoryStream。
JVMTI 代理,尤其是 jdwp 调试代理,也会造成内存消耗过多。
二 实例
2.1 一个很简单的Java程序内存占用: 15MB
Class: 5039 KB
Thread: 3042 KB
Code: 2557 KB
JavaHeap: 2048 KB
Symbol: 1742 KB
Internal: 230 KB
NativeMemoryTracking: 42 KB
ArenaChunk: 32 KB
GC: 19 KB
Total: 14751 KB [ Heap= 2048 , Thread= 3042 Class= 6781 , Other: 2880 ]
命令行:java -Xint -XX:+UseSerialGC -XX:NativeMemoryTracking=summary -Xmx1024k -Xss160K cn.PigEater
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode) java version "1.8.0_181"
SprintBoot Jar包 1.7MB .
2.2 一个功能简单的Spring Cloud微服务(使用redis/mybatis)内存占用:162MB
JavaHeap: 64 MB
Class: 62 MB
Symbol: 17 MB
Thread: 11 MB
NativeMemoryTracking: 3 MB
Code: 3 MB
Internal: 2 MB
Total: 162 MB [ Heap= 64 , Thread= 11 Class+Symbol= 79 , Other: 8 ]
命令行:java -XX:+UseSerialGC -XX:NativeMemoryTracking=summary -Xms64M -Xmx64M -Xss256k -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=64M -Xint -Deureka.client.serviceUrl.defaultZone=http://10.32.0.21:8761/eureka/ -jar target/user-kernel-server-0.0.1-SNAPSHOT.jar
SpringBoot Jar包 59MB
运行完10000条请求后内存占用:
Class: 68 MB
JavaHeap: 64 MB
Symbol: 18 MB
Thread: 14 MB
NativeMemoryTracking: 3 MB
Internal: 3 MB
Code: 3 MB
Total: 173 MB [ Heap= 64 , Thread= 14 Class= 86 , Other: 9 ]
2.3 功能简单的Spring Cloud微服务,使用Serial垃圾回收,64MB Heap内存,执行10000个请求后:220MB
Class: 75 MB
JavaHeap: 64 MB
Code: 41 MB
Thread: 18 MB
Symbol: 18 MB
NativeMemoryTracking: 3 MB
Internal: 3 MB
Total: 222 MB [ Heap= 64 , Thread= 18 Class= 93 , Other: 47 ]
命令行:java -XX:+UseSerialGC -XX:NativeMemoryTracking=summary -Xms64M -Xmx64M -Xss256k -Deureka.client.serviceUrl.defaultZone=http://10.32.0.21:8761/eureka/ -jar target/user-kernel-server-0.0.1-SNAPSHOT.jar
2.4 功能简单的Spring Cloud微服务,使用Serial垃圾回收,256MB Heap内存,执行10000个请求后:430MB
JavaHeap: 256 MB
Class: 74 MB
Code: 42 MB
Internal: 19 MB
Thread: 18 MB
Symbol: 18 MB
NativeMemoryTracking: 3 MB
GC: 1 MB
Total: 431 MB [ Heap= 256 , Thread= 18 Class= 92 , Other: 65 ]
命令行:java -XX:+UseSerialGC -XX:NativeMemoryTracking=summary -Xms256M -Xmx256M -Xss256k -Deureka.client.serviceUrl.defaultZone=http://10.32.0.21:8761/eureka/ -jar target/user-kernel-server-0.0.1-SNAPSHOT.jar
2.5 功能简单的Spring Cloud微服务,使用G1垃圾回收,256MB Heap内存,执行10000个请求后:510MB
JavaHeap: 256 MB
Class: 74 MB
GC: 59 MB
Code: 42 MB
Thread: 38 MB
Internal: 20 MB
Symbol: 18 MB
NativeMemoryTracking: 3 MB
Unknown: 0 MB
Total: 510 MB [ Heap= 256 , Thread= 38 Class= 92 , Other: 124 ]
三、微服务内存分配大致公式,以256MB Heap内存,Serial GC计算:
heap + 最大thread_num * 256k + jar_package_size * 3 + GC(Serial 0, CMS/G1 heap * 10%)
如:64MB heap, 60线程, jar包60MB,占用内存大约为 64 + 60 * 256k + 60 * 2 = 199 MB 可以正常动行,一般不会超过260 MB
512MB heap, 300线程,jar包120MB,占用内丰大约为 512 + 300 * 0.25MB + 120 * 2 = 830MB,一般不会超过950MB
使用策略 |
1.1 Heap |
1.2 Thread |
1.3 Class |
1.4 Symbol |
1.5 GC |
1.6 Code |
1.7 Internal |
1.8 Direct Buffer |
1.9 Native Library |
总计 |
---|---|---|---|---|---|---|---|---|---|---|
使用策略 |
1.1 Heap |
1.2 Thread |
1.3 Class |
1.4 Symbol |
1.5 GC |
1.6 Code |
1.7 Internal |
1.8 Direct Buffer |
1.9 Native Library |
总计 |
JDK1.8 分配方法 |
-Xmx256M 默认为机器内存的1/4 最小2MB |
-Xss256k 默认为1M 最小160k |
参考Jar包大小 加上JVM系统中必须的Jar包。 |
同1.3。 |
-XX:+UseSerialGC -XX:+UseG1GC 动态增长,默认与GC有关,SerialGC接近0。 |
-Xint -Xmixed 动态增长,与Jar包大小相关。 |
动态增长,与Jar包大小相关。 | 默认没有使用,大小为0。 | 默认没有使用,大小为0。 | |
2.1 简单Java程序 | 2MB | 3MB | 5MB | 1.7MB | 2.5MB | 15MB | ||||
2.2 微服务 | 64MB | 11MB | 62MB | 17MB | 3MB | 2MB | 162MB | |||
2.3 微服务 | 64MB | 18MB | 75MB | 18MB | 41MB | 3MB | 222MB | |||
2.4 微服务 | 256MB | 18MB | 74MB | 18MB | 42MB | 19MB | 431MB | |||
2.5 微服务+G1 | 256MB | 38MB | 74MB | 18MB | 59MB | 42MB | 20MB | 510MB | ||
2.6 微服务+G1 | 1024MB | 77MB | 80MB | 18MB | 81MB | 60MB | 53MB | 1398MB |
Java微服务内存占用分析相关推荐
- 运维:你们 JAVA 服务内存占用太高,还只增不减!告警了,快来接锅
先点赞再看,养成好习惯 某天,运维老哥突然找我:"你们的某 JAVA 服务内存占用太高,告警了!GC 后也没释放,内存只增不减,是不是内存泄漏了!" 然后我赶紧看了下监控,一切正常 ...
- 微服务调用事项;分析Java微服务优点
微服务调用事项 微服务=配置+流程+组件 微服务调用: 1.不要用api去调用api,比如report的实体类去继承collect实体类,容易导致有些接口情况出现report->collect, ...
- Java微服务 vs Go微服务,究竟谁更强!?
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 Java微服务能像Go微服务一样快吗?这是我最近一直 ...
- 从成本角度看Java微服务
近年来,微服务因其良好的灵活性和伸缩性等特点备受追捧,很多公司开始采用微服务架构或将已有的单体系统改造成微服务.IBM也于近日开源了轻量级Java微服务应用服务器Open Liberty.但是采用Ja ...
- 如何通过 Serverless 提高 Java 微服务治理效率?
作者 | 王科怀(行松) 来源 | 阿里巴巴云原生公众号 微服务治理面临的挑战 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发.但是随着公司的发展,会不断往系统里面添加新 ...
- Java微服务篇3——Lucene
Java微服务篇3--Lucene 1.数据分类 1.1.结构化数据 具有固定格式或有限长度的数据,如数据库,元数据等 常见的结构化数据也就是数据库中的数据,在数据库中搜索很容易实现,通常都是使用 s ...
- Java微服务篇2——SpringCloud
Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...
- Java微服务篇1——SpringBoot
Java微服务篇1--SpringBoot 1.什么是springboot 1.1.Spring出现的问题 Spring是Java企业版(Java Enterprise Edition,JEE,也称J ...
- Java 微服务框架选型(Dubbo 和 Spring Cloud?),大厂 HR 如何面试
写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 微服 ...
最新文章
- MapString, Object map 集合转 json数组, json数组转list ,按条输出到es
- shiro与springMVC整合
- MyGeneration【ui-原】
- 逆袭“潮牌”后,李宁离安踏还有多远?
- tensorflow的错误之Can not convert a float32 into a Tensor or Operation
- Hadoop集群部署模型纵览1
- 入门Python,这些优点你要知道
- GitHub 发布 2018 年开源项目趋势预测
- OPPO Find X2系列获蓝牙5.1认证:距离正式亮相又近了一步
- RunLoop运行循环机制
- 目前大数据工具主要哪些?
- Chrome和Firefox的xpi与crx加载第三方dll
- 高等数学上学习总结(集合,邻域,函数)
- 使用Ultra Librarian生成Cadence Allegro的PCB封装库和OrCAD Capture CIS的原理图库
- zabbix报警功能(邮件报警)---触发器/动作
- linux 防火墙 功能点,功能点(Funciton Point FP)估算法(三) 调整因子
- Spring Cloud微服务之Feign——声明式服务间调用
- GeoHash算法与用法
- 2022-8-15 第七小组 学习日记 (day39)Mysql数据库
- 对接支付宝手机网站支付接口,alin10071