题
我越来越OutOfMemoryError:java堆
片断的方法:
{
// step 1: I am creating a 2 dim array
int totalCombination = (int) Math.pow(2.0, (double) vowelCount);
// here vowelCount > 10
// step2: initializing my array
// step3: and using that array
}
我的问题:
每次这种方法被称为,这阵列是得到建立。它是可能的阵的不是获得释放。
在windows任务管理器,我可以看到存储器中使用通过java是纯粹渐进的。所以不是在一点堆尺寸小,但记忆是重复使用并不发布某种方式。
请让我知道如果你需要更多的detal.
请帮助调试的错误。
Anuj
一部分代码这可能是造成的错误:
int totalCombination=(int)数学。pow(2.0,(double)vowelCount);
int lookupArray[][] = new int[totalCombination][vowelCount];
// initialize lookupArray
for (int i = 0; i < totalCombination; i++) {
for (int j = 0; j < vowelCount; j++) {
lookupArray[i][j] = 0;
}
}
// populate lookupArray
//vowelCount : number of vowels in a word
// if count is 2, then array will contain 00,01,10,11
for (int i = 1; i < totalCombination; i++) {
for (int c = 0; c < vowelCount; c++) {
lookupArray[i][c] = lookupArray[i - 1][c];
}
boolean flag = true;
for (int j = vowelCount - 1; j >= 0 && flag; j--) {
if (lookupArray[i - 1][j] == 1) {
lookupArray[i][j] = 0;
} else if (lookupArray[i - 1][j] == 0) {
lookupArray[i][j] = 1;
flag = false;
}
}
}
// this part total combination of a word having different combination of vowels in it.
for (int i = 0; i < totalCombination; i++) {
int vcount = vowelCount - 1;
StringBuffer stringBuffer = new StringBuffer();
for (int j = 0; j < word.length(); j++) {
if (wordArr[j] == 'a' || wordArr[j] == 'e' || wordArr[j] == 'i'
|| wordArr[j] == 'o' || wordArr[j] == 'u') {
if (lookupArray[i][vcount] == 1) {
stringBuffer.append(wordArr[j]);
}
vcount--;
} else {
stringBuffer.append(wordArr[j]);
}
}
解决方案
权力的两个呈指数增长。如果 vowelCount
很高,一个阵就可以很容易导致 OutOfMemoryError
(2^32 = 4GB
).
你可以试着捏捏你的虚拟机的最大存储要求(例如 -Xmx512m
),但也意识到你的算法是要求 很多记忆.你可能想找到一个更好的算法,如果在所有可能的。
也参看
- 维基百科:指数级增长
- 小麦和棋盘上的问题 --着名的轶事显示是多么令人惊讶的是快速的权力的两个可以长
java
应用程序启动命令行选项- "
-Xmxn
:指定的最大尺寸的存分配水池"。
- "
后编辑:正如我预期,你在生成一个巨大的一系列充满了所有的二进制的可能性。你很少需要实际储存这一整个列在存储器。你可以生成每个可能的组合"飞行"并给它给谁需要的0和1"刚刚在时间"。
请记住,这仍然是指数增长,因此,即使你已经采取了照顾你的记忆要求从 O(2^N)
只是 O(N)
, ,您的时间复杂性还是 O(2^N)
.
每次这种方法被称为,这阵列是得到建立。它是可能的阵的不是获得释放。
是的,这是非常可能的,如果参照阵列是没有泄漏,那么一些地方持有到此参考。垃圾收集器真的不在乎什么 你的 想想是不是垃圾;只要作为一个目的是提到过的东西(它不是一个弱引用等等),它不是垃圾。
之后搞清楚你想要什么做的这是我的解决方案。注意它不会产生一系列的位。
static void generate(String prefix, String suffix) {
int i = suffix.replaceAll("[aeiou].*", "").length();
if (i == suffix.length()) {
System.out.println(prefix + suffix);
} else {
generate(prefix + suffix.substring(0, i), suffix.substring(i + 1));
generate(prefix + suffix.substring(0, i+1), suffix.substring(i + 1));
}
}
// generate("", "apple");
它使用regex找到下一个元音。你可以使用一个经常对环,而不是一般的算法将仍然起作用。你可以优化it使用 StringBuilder
而不是(我主要是要为简明和希望的清晰度,在这段).
这里有一个替代解决方案,使用 split
预砍输入串到条(O(N)
空间),那么使用 StringBuilder
产生的所有其他串(O(N)
空间)。
static void generate(StringBuilder sb, String[] parts, int i) {
if (i == parts.length) {
System.out.println(sb.toString());
} else {
if ("aeiou".contains(parts[i])) {
generate(sb, parts, i + 1);
}
sb.append(parts[i]);
generate(sb, parts, i + 1);
sb.setLength(sb.length() - parts[i].length());
}
}
static void generate(String s) {
generate(
new StringBuilder(),
s.split("(?<=[aeiou])|(?=(?!^)[aeiou])"),
0
);
}
// generate("apple");
Regex分裂 "apple"
入 [ "a", "ppl", "e" ]
.它无处不在的分裂后,一个元音,或(如果它是不是开始string)无处不在前一个元音。
这应该是显而易见,现在的空间要求 O(N)
, ,所以除非你是 可笑长, 这不应该导致 OutOfMemoryError
.
当然,如果你 储存 所产生的串--所有 O(2^N)
他们--在存储器然后 当然 你会得到 OutOfMemoryError
.我希望这一事实是显而易见的。
整个想法 是不存在记忆什么,你不需要产生这种巨大的输出。如果你然后储存所有这种巨大的输出,在存储器(而不是说,印刷他们 stdout
或者一个文件),那么它击败的整个目的,你会得到一个 OutOfMemoryError
如预期的.
其他提示
您可能要考虑使用一个分析器,它可以给你的东西存在在你的程序中的任何给定的时间类型的对象的图片。作为一个示例,NetBeans的具有内置分析器。
有了这样说,可能的罪魁祸首是 - 如已经指出的那样被他人 - 奇高量的存储器,您的二维阵列将需要作为元音计数生长
我假定您有类似下面的代码:
int totalCombination = 1 << vowelCount;
System.out.println("totalCombination = " + totalCombination);
System.out.println("totalCombination (in Millions) = " + totalCombination / 1000 / 1000);
int[] arr = new int[totalCombination];
在一个32位的虚拟机阵列永远不能进一步增长超过4GB,即为1024万个条目。确保您始终获得更小的数字在上面的代码打印出来。
也许你应该采取完全不同的算法。但是,你必须告诉我们你想达到的,而不是的如何的你想它。