如何在Java内存配置文件?如何在Java内存配置文件?(How to memory profile

2019-05-13 12:21发布

我仍然在学习Java很抱歉的绳索,如果有一个明显的答案。 我有一个正在一吨的内存中的程序,我想想法子,以减少其使用,但阅读很多做题后,我有我需要证明是哪里的问题之前,我开始优化它的想法。

因此,这里是我做什么,我增加了一个破发点,以我的程序的启动和运行它,然后我就开始VisualVM的,把它配置文件中的内存(我也没有在NetBeans同样的事情只是为了比较的结果和他们是一样的)。 我的问题是我不知道如何阅读,我得到了最高的区域只是说char[]我看不到任何代码或任何东西(这是有道理的,因为VisualVM的是连接到JVM并不能看到我的源,但也的NetBeans不显示我的来源,因为它做的CPU性能分析时一样)。

基本上我想知道的是哪个变量(希望更多的细节,如在该方法中)所有的内存被使用,因此我可以专注于在那里工作。 有没有一种简单的方法来做到这一点? 我现在我使用Eclipse和Java开发(和VisualVM的安装和NetBeans专门用于分析,但我愿意安装其他任何你觉得得到这个工作完成)。

编辑:理想情况下,我正在寻找的东西,将通过规模把我的所有对象,并对其进行排序(这样我就可以看到哪一个是占用内存)。 目前,它返回的通用信息,比如字符串[]或INT [],但我想知道哪个对象的引用这样我就可以得到它的尺寸更优化的工作。

Answer 1:

字符串是有问题

基本上在Java中, String引用(使用的东西char[]幕后)将智慧主宰大多数业务应用程序的内存。 它们是如何产生决定了它们在JVM的内存消耗。

仅仅因为他们是如此重要多数商业应用程序的数据类型,以及他们是最内存的一个饥饿为好。 这不只是一个Java的事情, String数据类型占用大量内存在几乎每一种语言和运行时库,因为在他们至少有1个字节的每个字符或坏(Unicode)的只是阵列它们阵列每个字符的多个字节。

一旦在web应用程序,也有一个Oracle JDBC的依赖剖析CPU使用率,当我发现StringBuffer.append()由多个数量级的占主导地位的CPU周期比所有其他方法调用相结合 ,更不用说其他任何单一的方法调用。 JDBC驱动程序做了很多很多的String操作,实物贸易的关使用PreparedStatements的一切。

你担心你无法控制,不能直接反正

你应该关注的是什么,在你的控制,这是确保你不会坚持到时间比你需要引用,你是不是不必要的重复的东西。 Java中的垃圾收集例程是高度优化的,如果你了解他们的算法是如何工作的,你可以确保你的程序在这些算法工作的最佳方式表现。

Java堆内存不喜欢手动管理的其他语言的记忆,这些规则不适用

其他语言什么被认为是内存泄漏是不一样的东西/根源在与Java垃圾收集系统。

最有可能在Java内存不是由正在泄漏(悬空在其它环境中参考)一个单一的超级对象消耗掉。

它是最有可能的,因为大量的较小的分配的StringBuffer / StringBuilder对象不是在第一instantantations适当大小,然后不得不自动增长char[]数组来保存后续append()调用。

这些中间对象可以围绕不再追究不是由垃圾收集预料的,因为范围的,他们是在和很多其他的东西,可以在运行时会有所不同。

比如:垃圾收集器可以决定有人选,但因为它认为有足够的内存仍然可以了,这可能是过于昂贵的时间明智冲出来在那个时间点,它会等到内存压力变高。

垃圾收集器现在是非常好的,但它不是魔术,如果你正在做的事情退化,这将导致其不能很好地工作。 有大量的文件大约为JVM中的所有版本的垃圾收集器设置在互联网上。

这些未引用的对象可能只是还没有达到垃圾收集器认为它他们需要为他们从内存中清除,或者可能有一些其它物体(保持对它们的引用的时间List例如,你不要”)牛逼REALIZE仍指向该对象。 这是最通常被称为Java中的漏洞 ,这是一个参考泄漏更具体。

例如:如果你知道你需要建立一个4K String使用StringBuilder与创建new StringBuilder(4096); 不是默认的,这就好比32,并立即开始创建的垃圾,可以代表很多时候你怎么想的对象应该是大小明智的。

你可以发现有多少什么类型的对象与VisualVM的实例化,这会告诉你你需要知道的东西。 还有就是不会成为一个大的闪烁光指向在一个类,说的一个实例,“这是大内存的消费者!”,那就是除非有一些只有一个实例char[]你是读了一些大规模的文件到了,这是不可能的或者,因为很多其他类使用char[]内; 然后你很可能已经知道了。

我没有看到任何提及OutOfMemoryError

你可能没有问题,在你的代码,垃圾收集系统只是可能无法获得足够的下压力,以踢,你认为它应该被清理取消分配的对象放。 你认为什么可能是一个问题没有,没有,除非你的程序与崩溃OutOfMemoryError 。 这不是C,C ++,Objective-C中,或任何其它手工存储器管理的语言/运行时。 你没有得到决定什么是内存或没有你期待你应该能够给详细度。



Answer 2:

在JProfiler的 ,你可以采取去堆沃克和激活的最大对象视图。 您将看到物体保留了大部分内存。 “保留”记忆是会被垃圾收集器,如果你删除的对象被释放的内存。

然后,您可以打开对象节点看到保留的对象的引用树。 这里是最大的对象视图的屏幕截图:

免责声明:我公司开发的JProfiler



Answer 3:

我会建议捕获堆转储和使用类似的工具Eclipse的MAT ,可以让你对它们进行分析。 有很多的教程可用。 它提供的视图支配树提供洞察堆上的对象之间的关系。 特别是对于你所提到的,在“路径的GC根” MAT的功能会告诉你那些的多数的char []的String []和INT []被引用的对象在哪里。 JVisualVM也可以在识别泄漏和分配,特别是通过使用与分配栈跟踪快照是有用的。 有相当多的过程中穿行得到的快照,并比较他们找到的分配点。



Answer 4:

Java的JDK自带JVisualVM,一旦你的应用程序服务器(例如运行),您可以运行VisualVM的,并将其连接到localhost,这将提供给您的内存分配,使您能够执行堆转储bin文件夹下

有关如何让更多的详细步骤: http://sysdotoutdotprint.com/technologies/java/6



Answer 5:

如果您使用的VisualVM检查你的内存使用,它着重于数据,而不是方法。 也许你的大的char []数据是由许多字符串值造成的? 除非你使用递归,数据将无法从局部变量。 所以,你可以专注于将元素插入到大型数据结构的方法。 要了解精确的语句将导致你的“内存泄露”,我建议你还

  • 阅读乔希布洛赫的有效的Java项目6:(淘汰落后对象引用)
  • 使用日志框架的上的最高冗长级别日志实例的创作。


文章来源: How to memory profile in Java?