• 生活小妙招免费各类生活中的小问题知识以及音乐简谱等,是你了解世界未知知识的好地方。

java程序消耗内存太大怎么办?应该如何解决?

十万个为什么 空空 2024-4-08 17:40:52 5次浏览

关于问题java 程序消耗内存太大怎么办?应该如何解决?一共有 4 位热心网友为你解答:

【1】来自网友【华为云开发者联盟】的最佳回答:

摘要:4 种查看 java 对象所占内存大小的方法

计算 java 对象所占内存大小

1.使用 jdk8 自带 API

使用这种 jdk8 方式时,Open JDK 不是天然支持的,需要设置一下环境变量

结果如下:

2. 借助 org.apache.lucene 工具类

当一个对象有多个属性,需要计算整个对象的大小时,可以借助 org.apache.lucene 工具类

先引入 maven 坐标

测试代码:

结果如下:

3. 借助 jol 工具类

如果需要查看某个对象的详细内存分布,可以借助 jol 工具类,不过这种当对象中内嵌其他对象时,只能计算 ClassLayout 方法中这个 object 对象所占内存的大小

先导入 maven 坐标

测试代码:

结果如下:

4.java 对象内存分布

最后,计算一个对象占用多大内存,需要提前了解 java 对象的布局。

本文分享自华为云社区《查看 java 对象所占内存大小-云社区-华为云》,作者:xiewenci。

【2】来自网友【道法如飞】的最佳回答:

首先与大多语言一样,Java 内存也分为堆内存(Heap)和栈内存(Stack)。

Java 有 8 种基本数据类型(int、short、byte、char、double、float、long、boolean)再加上对象引用(reference 类型,它不等同于对象本身,而指向对象起始地址的引用指针。)基本数据存在栈中,对象数据存放在堆中。

Java 以下两种内存异常情况:

1. 如果线程请求的栈深度大于虚拟机允许的深度,将抛出 StackOverflowError 异常;2. 如果虚拟机栈可以动态扩展,在扩展时无法申请到足够的内存,就会抛出 OutOfMemoryError 异常。

如果内存没有被及时回收造成内存占用失控主要有以下两种情况:

1. 内存泄露(Memory Leak):程序在申请内存后,对象没有被 GC 所回收,它始终占用内存,内存泄漏的堆积最终会造成内存溢出。

2. 内存溢出(Memory Overflow):程序运行过程中无法申请到足够的内存而导致的一种错误。内存溢出通常发生于 OLD 段或 Perm 段垃圾回收后,仍然无内存空间容纳新的 Java 对象的情况。通常都是由于内存泄露导致堆栈内存不断增大,从而引发内存溢出。

所以,如果程序大量占用内存而无法释放,要么是内存泄漏要么是内存溢出。排查方式包括:

1. 代码调试和日志排查,看哪里有循环引用、死循环、内存泄漏和溢出等情况。

2. 利用 Java 的工具分析内存占用情况:

jinfo:可以输出并修改运行时的 java 进程的 opts。

jps:与 unix 上的 ps 类似,用来显示本地的 java 进程,可以查看本地运行着几个 java 程序,并显示他们的进程号。

jstat:一个极强的监视 VM 内存工具。可以用来监视 VM 内存内的各种堆和非堆的大小及其内存使用量。

jmap:打印出某个 java 进程(使用 pid)内存内的所有‘对象‘的情况(如:产生那些对象,及其数量)。

jconsole:一个 java GUI 监视工具,可以以图表化的形式显示各种数据。并可通过远程连接监视远程的服务器 VM。

3. 利用专门内存分析工具:

MAT(Memory Analyzer Tool)

JProfiler

GC Viewer

VisualVM

Profiler4J

程序占用内存大排查是个不容易的过程,需要一点耐心和经验。

【3】来自网友【歪歪派派】的最佳回答:

谢谢邀请,Java 内存消耗太大,首先要检查内存中的对象是不是真的必不可少,如果真的是必不可少的,那就只能扩大系统内存,如果检查发现内存中的对象不是比不可少的,那就可以着手优化代码,将那些对象释放(通过设置为 null 是一种方式),然后垃圾收集器就可以进行回收,以释放内存,提高内存的周转率。我们都知道 Java 回收对象是根据可达性分析算法来判定对象是否可以进行回收的,也就是 JVM 有一些 GC Root 根节点,通过判断堆内存中的对象是否可以到达这些节点,如果不能到达,则 GC 便可以进行回收,而可达的对象则不会被回收,所以我们可以通过这个特性做一些简单判断,然后再借助 Java 提供的一些实用工具和命令或其他专业分析工具进行精准分析即可。

【4】来自网友【飞飞 lin】的最佳回答:

补充楼上几位的回答,如果最后发现不是内存溢出,而是程序正常的需要,那可以考虑把需要的数据放入到 redis 去,而不是存储在 java 程序的变量里面。

这样子可以极大的降低内存内存消耗,又可以方便程序的集群部署、数据共享

喜欢 (0)