相关疑难解决方法(0)

将ArrayList转换为字符串的最佳方法

我有一个ArrayList我想完全输出为String.基本上我想按顺序输出它,使用toString由制表符分隔的每个元素.有没有快速的方法来做到这一点?你可以循环它(或删除每个元素)并将它连接到一个字符串,但我认为这将是非常缓慢的.

java string arraylist

353
推荐指数
17
解决办法
101万
查看次数

Java OutOfMemoryError奇怪的行为

假设我们的最大内存为256M,为什么这段代码有效:

public static void main(String... args) {
  for (int i = 0; i < 2; i++)
  {
      byte[] a1 = new byte[150000000];
  }
  byte[] a2 = new byte[150000000];
}
Run Code Online (Sandbox Code Playgroud)

但是这个扔了一个OOME?

public static void main(String... args) {
  //for (int i = 0; i < 2; i++)
  {
      byte[] a1 = new byte[150000000];
  }
  byte[] a2 = new byte[150000000];
}
Run Code Online (Sandbox Code Playgroud)

java out-of-memory

55
推荐指数
2
解决办法
1957
查看次数

为什么java等待这么长时间来运行垃圾收集器?

我正在使用Play构建一个Java Web应用程序!框架.我在playapps.net上托管它.在提供的内存消耗图表上,我一直困惑不已.这是一个示例:

堆内存

该图表来自一致但名义上的活动期.我没有做任何事情来触发内存的衰减,所以我认为这是因为垃圾收集器运行,因为它几乎达到了允许的内存消耗.

我的问题:

  • 它是公平的,我认为我的应用程序并不会有内存泄漏,因为它似乎是所有内存都被正确地被垃圾回收器回收它在运行时?
  • (从标题)为什么java等到最后一秒可能运行垃圾收集器?随着内存消耗增长到图表的前四分之一,我看到显着的性能下降.
  • 如果我的断言是正确的,那么我该如何解决这个问题?我在SO上读过的其他帖子似乎反对调用System.gc(),范围从中性("它只是运行GC的请求,所以JVM可能只是忽略你")完全反对("依赖的代码System.gc()从根本上被打破") .或者我不在这里,我应该在我自己的代码中寻找导致此行为和间歇性性能损失的缺陷?

更新
我已经在PlayApps.net上开启了一个关于这个问题的讨论,并在这里提到了一些观点; 特别是@Affe关于完整GC设置非常保守的评论,以及@ G_H关于初始和最大堆大小设置的评论.

这是讨论链接,但遗憾的是您需要一个playapps帐户才能查看.

当我得到它时,我会在这里报告反馈; 非常感谢大家的回答,我已经从中学到了很多东西!

解决方案
Playapps支持,这仍然很好,对我没有很多建议,他们唯一的想法是,如果我广泛使用缓存,这可能会使对象保持活动的时间超过需要,但事实并非如此.我还是学到了很多东西(呜呜!),我给了@Ryan Amos绿色支票,因为我提出了他System.gc()每半天打电话的建议,现在工作正常.

java memory memory-management playframework

49
推荐指数
3
解决办法
7284
查看次数

是否有一个内存有效的java.lang.String替换?

在阅读了这篇测量几种对象类型的内存消耗的旧文章后,我惊讶地发现String在Java中使用了多少内存:

length: 0, {class java.lang.String} size = 40 bytes
length: 7, {class java.lang.String} size = 56 bytes
Run Code Online (Sandbox Code Playgroud)

虽然文章有一些提示,以尽量减少这种情况,但我发现它们并不完全令人满意.char[]用于存储数据似乎是浪费的.大多数西方语言的明显改进是使用byte[]和编码类似UTF-8,因为你只需要一个字节来存储最频繁的字符,而不是两个字节.

当然可以使用String.getBytes("UTF-8")new String(bytes, "UTF-8").甚至String实例本身的开销也会消失.但后来有你失去像非常方便的方法equals(),hashCode(),length(),...

Sun有一个专利byte[]字符串表示,据我可以告诉.

用于在Java编程环境中高效表示字符串对象的框架
......可以实现这些技术,以便在适当时将Java字符串对象创建为单字节字符的数组...

但是我找不到该专利的API.

我为什么在意?
在大多数情况下,我没有.但我使用包含大量字符串的巨大缓存来处理应用程序,这些字符串可以从更有效地使用内存中受益.

有人知道这样的API吗?或者是否有另一种方法可以保持Strings的内存占用空间小,即使以CPU性能或更丑陋的API为代价?

请不要重复上述文章中的建议:

  • 自己的变种String.intern()(可能与SoftReferences)
  • 存储单个char[]并利用当前String.subString(.)实现来避免数据复制(讨厌)

更新

我从Sun目前的JVM(1.6.0_10)上的文章中运行了代码.它产生了与2002年相同的结果.

java memory string optimization performance

36
推荐指数
6
解决办法
2万
查看次数

为什么垃圾收集者在解除分配之前会等待?

我有一个"为什么这样做?" 关于垃圾收集的问题(任何/所有实现:Java,Python,CLR等).当垃圾收集器不再处于任何范围内时,它会释放该对象; 指向它的引用数为零.在我看来,一旦引用数量达到零,框架就可以解除分配,但我遇到的所有实现都会等待一段时间,然后一次解除分配许多对象.我的问题是,为什么?

我假设框架为每个对象保留一个整数(我认为Python会这样做,因为你必须调用PyINCREFPyDECREF在C中为它编写扩展模块时;可能这些函数在某处修改了一个真正的计数器).如果是这样,那么它不应该花费更多的CPU时间来消除对象超出范围的时刻.如果现在每个对象需要x纳秒,那么以后每个对象需要x纳秒,对吗?

如果我的假设是错误的并且没有与每个对象关联的整数,那么我理解为什么垃圾收集等待:它必须走引用图以确定每个对象的状态,并且该计算需要时间.这样的方法比显式引用计数方法消耗更少的内存,但我很惊讶它更快或者是其他原因的首选方法.这听起来像是很多工作.

从编程的角度来看,如果对象在超出范围后立即释放,那将会很好.我们不仅可以依赖于在我们希望它们执行时执行的析构函数(其中一个Python陷阱是__del__在可预测的时间没有调用),但是对程序进行内存配置会变得更加容易. 这是一个由此引起的混淆的例子.在我看来,在deallocate-right-away框架中编程的好处是如此之大,以至于为什么我所听到的所有实现在解除分配之前都要等待.这有什么好处?

注意:如果遍历引用图只需要识别循环引用(纯引用计数不能),那么为什么不采用混合方法呢?一旦引用计数达到零,就释放对象,然后进行定期扫描以查找循环引用.在这样的框架中工作的程序员将有一个性能/决定论理由,尽可能地坚持非循环引用.它通常是可行的(例如,所有数据都是JSON对象的形式,没有父指针).这是流行垃圾收集器的工作原理吗?

garbage-collection reference-counting

18
推荐指数
3
解决办法
2498
查看次数