如何在Java中创建内存配置文件?

如何在Java中创建内存配置文件?,java,profiling,visualvm,Java,Profiling,Visualvm,我仍在学习Java的诀窍,如果有一个明显的答案,我很抱歉。我有一个占用大量内存的程序,我想找到一种方法来减少它的使用,但在阅读了这么多问题后,我有了一个想法,我需要在开始优化它之前证明问题在哪里 这就是我所做的,我在程序的开头添加了一个断点并运行它,然后启动visualVM并让它分析内存(我在netbeans中也做了同样的事情,只是为了比较结果,结果是一样的)。我的问题是我不知道如何读取它们,我得到的最高区域只是说char[],我看不到任何代码或任何东西(这是有意义的,因为visualvm连接到

我仍在学习Java的诀窍,如果有一个明显的答案,我很抱歉。我有一个占用大量内存的程序,我想找到一种方法来减少它的使用,但在阅读了这么多问题后,我有了一个想法,我需要在开始优化它之前证明问题在哪里

这就是我所做的,我在程序的开头添加了一个断点并运行它,然后启动visualVM并让它分析内存(我在netbeans中也做了同样的事情,只是为了比较结果,结果是一样的)。我的问题是我不知道如何读取它们,我得到的最高区域只是说
char[]
,我看不到任何代码或任何东西(这是有意义的,因为visualvm连接到jvm,看不到我的源代码,但netbeans也没有像进行cpu评测时那样显示源代码)

基本上,我想知道的是所有的内存都在使用哪个变量(希望还有更多的细节,比如哪个方法),这样我就可以集中精力在那里工作了。有没有一个简单的方法可以做到这一点?我现在正在使用eclipse和java进行开发(并安装了visualVM和netbeans专门用于评测,但我愿意安装您认为可以完成此工作的任何其他东西)


编辑:理想情况下,我正在寻找一种可以将我所有的对象按大小排序的东西(这样我就可以看到哪一个占用了内存)。目前,它返回字符串[]或int[]之类的一般信息,但我想知道它引用的对象,以便我可以对其大小进行更优化。

字符串有问题。

基本上在Java中,
String
引用(在后台使用
char[]
的东西)将主导大多数业务应用程序的内存。它们的创建方式决定了它们在JVM中消耗的内存量

这仅仅是因为它们作为一种数据类型对大多数业务应用程序来说非常重要,而且它们也是最需要内存的应用程序之一。这不仅仅是Java的事情,
String
数据类型在几乎所有语言和运行时库中都会占用大量内存,因为它们至少是每个字符1字节的数组,或者更糟糕的是(Unicode),它们是每个字符多字节的数组

有一次,当我在一个同样依赖Oracle JDBC的web应用程序上分析CPU使用情况时,我发现
StringBuffer.append()
在所有其他方法调用组合的中占据了CPU周期的多个数量级,更不用说任何其他单个方法调用了。JDBC驱动程序做了大量的
String
操作,在某种程度上是对一切使用
PreparedStatements
的权衡

你所关心的是你无法控制的,无论如何不能直接控制

你应该关注的是你控制中的内容,这就是确保你对引用的保留时间不会超过你需要的时间,并且你不会不必要地重复内容。Java中的垃圾收集例程经过了高度优化,如果您了解了它们的算法是如何工作的,您可以确保您的程序以最佳方式运行,以使这些算法能够工作

Java堆内存不像其他语言中的手动管理内存,这些规则不适用

在其他语言中被认为是内存泄漏的原因与Java的垃圾收集系统不同

很可能Java内存中没有一个uber对象泄漏(其他环境中的悬空引用)

这很可能是由于
StringBuffer
/
StringBuilder
对象在第一个瞬间大小不合适,然后必须自动增加
char[]
数组以容纳后续的
append()
调用而导致的分配量减少

由于这些中间对象所处的范围以及运行时可能发生的许多其他变化,它们可能比垃圾收集器预期的时间长

示例:垃圾收集器可能会决定是否有候选内存,但由于它认为还有大量内存需要使用,因此在该时间点清除这些内存可能会花费太多时间,它将等待内存压力变大

垃圾收集器现在真的很好,但它不是魔法,如果你做的是退化的事情,它将导致它无法最佳工作。互联网上有很多关于所有JVM版本的垃圾收集器设置的文档

这些未引用的对象可能还没有达到垃圾回收器认为从内存中删除它们所需的时间,或者其他对象(
List
)可能持有对它们的引用,例如,您没有意识到仍然指向该对象。这是Java中最常见的泄漏,更具体地说是引用泄漏

示例:如果您知道需要使用
StringBuilder构建4K
字符串
,请使用
新建StringBuilder创建它(4096)不是默认值,它类似于32,并将立即开始创建垃圾,垃圾可以表示您认为对象大小应该是多少倍

您可以发现使用VisualVM实例化了多少种类型的对象,这将告诉您需要了解的内容。不会有一个大的闪光灯指向一个类的一个实例,它会说,“这是大内存消费者!”,除非只有一个
char[]
的实例,你正在读取一些大文件,这也是不可能的,因为很多其他类都使用
char[]
内部;然后你就知道了

我没有看到任何关于
OutOfMemoryError的提及