一、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微服务内存占用分析相关推荐

  1. 运维:你们 JAVA 服务内存占用太高,还只增不减!告警了,快来接锅

    先点赞再看,养成好习惯 某天,运维老哥突然找我:"你们的某 JAVA 服务内存占用太高,告警了!GC 后也没释放,内存只增不减,是不是内存泄漏了!" 然后我赶紧看了下监控,一切正常 ...

  2. 微服务调用事项;分析Java微服务优点

    微服务调用事项 微服务=配置+流程+组件 微服务调用: 1.不要用api去调用api,比如report的实体类去继承collect实体类,容易导致有些接口情况出现report->collect, ...

  3. Java微服务 vs Go微服务,究竟谁更强!?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 Java微服务能像Go微服务一样快吗?这是我最近一直 ...

  4. 从成本角度看Java微服务

    近年来,微服务因其良好的灵活性和伸缩性等特点备受追捧,很多公司开始采用微服务架构或将已有的单体系统改造成微服务.IBM也于近日开源了轻量级Java微服务应用服务器Open Liberty.但是采用Ja ...

  5. 如何通过 Serverless 提高 Java 微服务治理效率?

    作者 | 王科怀(行松) 来源 | 阿里巴巴云原生公众号 微服务治理面临的挑战 在业务初期,因人手有限,想要快速开发并上线产品,很多团队使用单体的架构来开发.但是随着公司的发展,会不断往系统里面添加新 ...

  6. Java微服务篇3——Lucene

    Java微服务篇3--Lucene 1.数据分类 1.1.结构化数据 具有固定格式或有限长度的数据,如数据库,元数据等 常见的结构化数据也就是数据库中的数据,在数据库中搜索很容易实现,通常都是使用 s ...

  7. Java微服务篇2——SpringCloud

    Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...

  8. Java微服务篇1——SpringBoot

    Java微服务篇1--SpringBoot 1.什么是springboot 1.1.Spring出现的问题 Spring是Java企业版(Java Enterprise Edition,JEE,也称J ...

  9. Java 微服务框架选型(Dubbo 和 Spring Cloud?),大厂 HR 如何面试

    写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 微服 ...

最新文章

  1. MapString, Object map 集合转 json数组, json数组转list ,按条输出到es
  2. shiro与springMVC整合
  3. MyGeneration【ui-原】
  4. 逆袭“潮牌”后,李宁离安踏还有多远?
  5. tensorflow的错误之Can not convert a float32 into a Tensor or Operation
  6. Hadoop集群部署模型纵览1
  7. 入门Python,这些优点你要知道
  8. GitHub 发布 2018 年开源项目趋势预测
  9. OPPO Find X2系列获蓝牙5.1认证:距离正式亮相又近了一步
  10. RunLoop运行循环机制
  11. 目前大数据工具主要哪些?
  12. Chrome和Firefox的xpi与crx加载第三方dll
  13. 高等数学上学习总结(集合,邻域,函数)
  14. 使用Ultra Librarian生成Cadence Allegro的PCB封装库和OrCAD Capture CIS的原理图库
  15. zabbix报警功能(邮件报警)---触发器/动作
  16. linux 防火墙 功能点,功能点(Funciton Point FP)估算法(三) 调整因子
  17. Spring Cloud微服务之Feign——声明式服务间调用
  18. GeoHash算法与用法
  19. 2022-8-15 第七小组 学习日记 (day39)Mysql数据库
  20. 对接支付宝手机网站支付接口,alin10071

热门文章

  1. LAMP介绍、Apache安装
  2. 文言编程语言/wenyan-lang
  3. js render 函数
  4. ajax用jquery怎么实现,ajax使用jquery的实现方式
  5. 浏览器禁用ajax,禁用浏览器缓存Ajax请求
  6. bat cmd 获取管理员权限
  7. 2021-06-28 北京银联商务有限公司
  8. 五分钟告诉你什么是MySQL的覆盖索引
  9. 漫步者蓝牙自动断开_用心感受音乐带来的愉悦——漫步者W2真无线蓝牙耳机评测...
  10. python transpose与permute函数详解