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

用户 华为云开发者联盟 的回答

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

计算java对象所占内存大小

1.使用jdk8自带API

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

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

 

结果如下:

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

 

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

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

先引入maven坐标

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

 

测试代码:

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

 

结果如下:

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

 

3. 借助jol工具类

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

先导入maven坐标

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

 

测试代码:

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

 

结果如下:

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

 

4.java对象内存分布

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

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

用户 道法如飞 的回答

首先与大多语言一样,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

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

用户 歪歪派派 的回答

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

(0)

相关推荐