这些占用堆中的空间
字符串:明智地使用String,尝试使用局部变量,确保没有没有引用的字符串并尝试使用StringBuffer或StringBuilder
静态:明智地使用静态
实例变量:尝试尽可能在本地声明变量
对象:尽可能重用
如果到目前为止,请纠正我错误...还建议我在Java编程时可以采取更多预防措施来减少堆空间的使用
答案 0 :(得分:3)
您需要更加具体地了解您要实现的目标。有两个目标(在某些情况下)是矛盾的:
静态:明智地使用静态
这是毫无意义的建议,除非你说“明智的用处”。
字符串:明智地使用String,尝试用作局部变量,确保没有没有引用的字符串并尝试使用StringBuffer或StringBuilder
实例变量:尝试尽可能在本地声明变量
这通常是合理的建议,但需要与其他事物保持平衡。
对象:尽可能重用
这是不好的建议。
重用“尽可能”意味着对象池,并且对象池倾向于使用更多堆空间,而不是只丢弃对象并让GC回收它。只有在最小化对象创建速率至关重要时才应使用对象池。即使这样,你也需要非常小心避免:
答案 1 :(得分:2)
以下几点可以帮助提高应用程序的内存利用率如果明智地使用。但是请注意它们并不是普遍适用的,如果你不明白你在做什么,你会得到一个糟糕的结果....一个更复杂的程序,几乎没有任何内存使用的改进。
许多标准的Java集合类型都非常需要内存。例如,ArrayList<Integer>
包含2个要开始的对象,以及每个数组元素的额外对象(取决于元素的创建方式......)。此外,ArrayList
的后备阵列可能比它需要的大。相比之下,int[]
只包含一个对象,每个元素只使用一个32位字。
(可以对更复杂的数据结构进行类似的比较,特别是当基类型是基本类型时。有第三方库实现这种东西;例如GNU Trove库。)
很明显,如果仔细设计数据结构,可以使用更少的内存和更少的对象来表示它们。
然而,另一方面,这往往会使您的应用程序更复杂,更难维护。例如:
使用int[]
代替ArrayList<Integer>
会导致更多实施细节曝光,并增加耦合。
使用数组来表示变量或不确定大小的列表很棘手。
许多API旨在采用List
或Collection
参数而不是数组参数。因此,您更有可能必须开发自己的自定义非集合版本的库代码。
泛型和数组不能很好地混合。
总之,虽然您可以节省堆空间,但可能最终以其他方式付款。
String
和BigInteger
等类的实例在设计上是不可变的。这简化了计算模型,但这意味着“改变”某些事情涉及创建新对象。您通常可以通过以下方式减少内存使用量:
使用类型的可变版本;例如使用StringBuilder
/ StringBuffer
代替String
或
使您自己的应用程序数据类可变而不是不可变。
再次,有一个反面。可变数据结构可能导致更复杂;例如如果您的应用程序是多线程的,或者您需要能够撤消回溯或某些步骤失败的事情。这使您的应用程序更加复杂。在某些情况下,唯一可行的解决方案是复制数据结构,从而使用更多内存。
总之,虽然您可以节省堆空间,但可能最终以其他方式付款。你甚至可能最终都不会节省记忆。
答案 2 :(得分:0)
这很不错。要注意的另一件事是正确关闭你的缓冲区类型对象,我的意思是套接字,文件阅读器等等......确保你将它们包装在最后,最后你记得在哪里刷新(如果需要)和关闭连接/缓冲区。这可以避免因为底层连接仍然处于活动状态而保留杂散资源。
答案 3 :(得分:0)
同样关于字符串的主题,在从文件或数据库中读取时总是intern()
,所以你最终不会有重复的字符数组。
答案 4 :(得分:-1)
首先:测量哪些对象占用最多的堆空间:jmap -histo:live
然后尝试减少前五个班级。而已。再次测量。重复,直到你满意为止。
如果其中一个候选者是HashMap
或HashSet
或ConcurrentHashMap
:这些类会尽可能地浪费堆内存。为他们使用节省内存的替代品。