垃圾收集问题
我编写了一个接受 .obj 文件的 ObjectLoader,它给了我我想要的东西。 我的问题是,当处理大文件(甚至没有那么大,大约80kb)时,我最终 最终无法获取所有信息,因为它会在一段时间后停止读取。
在我完成之前,我在 LogCat 中得到了这个,调试器只需继续执行下一个方法:
DEBUG/dalvikvm(25743): GC_FOR_MALLOC 在 50 毫秒内释放了 2076 个对象/124280 个字节
DEBUG/dalvikvm(25743):GC_FOR_MALLOC 在 52 毫秒内释放了 4 个对象/232 字节
DEBUG/dalvikvm(25743):GC_FOR_MALLOC 在 49 毫秒内释放了 142 个对象/46728 字节
DEBUG/dalvikvm(25743):GC_FOR_MALLOC 在 53 毫秒内释放了 0 个对象/0 个字节 DEBUG/dalvikvm(25743):GC_FOR_MALLOC 在 39 毫秒内释放了 533 个对象/63504 字节
DEBUG/dalvikvm(25743): GC_FOR_MALLOC 在 50 毫秒内释放了 4 个对象/216 字节
DEBUG/dalvikvm(25743):GC_EXTERNAL_ALLOC 在 40 毫秒内释放了 132 个对象/26768 字节
换句话说,我猜有很多垃圾收集。仅仅是因为我在代码中分配了很多内存吗?如果是这样,有什么我需要阅读的基础知识吗?或者您还有其他建议吗?我使用 4 个向量,每个向量最终包含大约 2K-3K 个对象。 编辑:实际上有 7 个向量,另外 3 个用于携带索引,但我仍然认为没有那么多。
private void readObj(InputStreamReader in) throws IOException
{
BufferedReader reader = null;
String line = null;
reader = new BufferedReader(in);
while ((line = reader.readLine()) != null)
{
Log.v(TAG, line);
if (line.startsWith("f"))
{
faces++;
processFLine(line);
} else if (line.startsWith("vn"))
{
normals++;
processVNLine(line);
} else if (line.startsWith("vt"))
{
UVCoords++;
processVTLine(line);
} else if (line.startsWith("v"))
{
vertices++;
processVLine(line);
}
}
}
private void processVNLine(String line)
{
String[] tokens = line.split("[ ]+");
int c = tokens.length;
for (int i = 1; i < c; i++)
{
_vn.add(Float.valueOf(tokens[i]));
}
}
private void processFLine(String line)
{
String[] tokens = line.split("[ ]+");
int c = tokens.length;
if (tokens[1].matches("[0-9]+"))
{
caseFEqOne(tokens, c);
}
if (tokens[1].matches("[0-9]+/[0-9]+"))
{
caseFEqTwo(tokens, c);
}
if (tokens[1].matches("[0-9]+//[0-9]+"))
{
caseFEqOneAndThree(tokens, c);
}
if (tokens[1].matches("[0-9]+/[0-9]+/[0-9]+"))
{
caseFEqThree(tokens, c);
}
}
private void caseFEqThree(String[] tokens, int c)
{
for (int i = 1; i < c; i++)
{
Short s = Short.valueOf(tokens[i].split("/")[0]);
s--;
_vPointer.add(s);
s = Short.valueOf(tokens[i].split("/")[1]);
s--;
_vtPointer.add(s);
s = Short.valueOf(tokens[i].split("/")[2]);
s--;
_vnPointer.add(s);
}
}
Iv'e coded a ObjectLoader that takes a .obj file and it gives me what i want.
My problem is that when handling big files(not even that big, about 80kb) i eventually
end up with not getting all information because it stops reading after a while.
I get this in my LogCat before im done and debuger simply moves on to next method:
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 2076 objects / 124280 bytes in 50ms
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 4 objects / 232 bytes in 52ms
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 142 objects / 46728 bytes in 49ms
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 0 objects / 0 bytes in 53ms
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 533 objects / 63504 bytes in 39ms
DEBUG/dalvikvm(25743): GC_FOR_MALLOC freed 4 objects / 216 bytes in 50ms
DEBUG/dalvikvm(25743): GC_EXTERNAL_ALLOC freed 132 objects / 26768 bytes in 40ms
In other words, alot of Garbage Collection i guess. Is it simply because i allocate to much memory in my code? And if so, is there any basics I need to read into or do you have any other suggestions? I'm using 4 Vectors each ending up holding about 2K-3K objects.
Edit: There's acctually 7 vectors, 3 extra for carrying indexes, but still i don't think it's that much.
private void readObj(InputStreamReader in) throws IOException
{
BufferedReader reader = null;
String line = null;
reader = new BufferedReader(in);
while ((line = reader.readLine()) != null)
{
Log.v(TAG, line);
if (line.startsWith("f"))
{
faces++;
processFLine(line);
} else if (line.startsWith("vn"))
{
normals++;
processVNLine(line);
} else if (line.startsWith("vt"))
{
UVCoords++;
processVTLine(line);
} else if (line.startsWith("v"))
{
vertices++;
processVLine(line);
}
}
}
private void processVNLine(String line)
{
String[] tokens = line.split("[ ]+");
int c = tokens.length;
for (int i = 1; i < c; i++)
{
_vn.add(Float.valueOf(tokens[i]));
}
}
private void processFLine(String line)
{
String[] tokens = line.split("[ ]+");
int c = tokens.length;
if (tokens[1].matches("[0-9]+"))
{
caseFEqOne(tokens, c);
}
if (tokens[1].matches("[0-9]+/[0-9]+"))
{
caseFEqTwo(tokens, c);
}
if (tokens[1].matches("[0-9]+//[0-9]+"))
{
caseFEqOneAndThree(tokens, c);
}
if (tokens[1].matches("[0-9]+/[0-9]+/[0-9]+"))
{
caseFEqThree(tokens, c);
}
}
private void caseFEqThree(String[] tokens, int c)
{
for (int i = 1; i < c; i++)
{
Short s = Short.valueOf(tokens[i].split("/")[0]);
s--;
_vPointer.add(s);
s = Short.valueOf(tokens[i].split("/")[1]);
s--;
_vtPointer.add(s);
s = Short.valueOf(tokens[i].split("/")[2]);
s--;
_vnPointer.add(s);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如你们所说,这不是垃圾收集器的错。这是 LogCat 的错。并不是它打印出了关于垃圾收集的那些行,而是它没有打印出我在循环完成时使用的 Log.i(tag, string) 。 (在循环期间我使用了 Log.v()。所以它实际上并没有给我不完整的结果,我只是无法看到完整的结果或它实际上完成了。
As you all said, it wasn't the garbage collectors fault. It was the LogCat's fault. And not the fact that it printed out those line about the garbage collecting, it's about the fact that it didn't print out my Log.i(tag, string) that I used when the loop was finished. (During the loop I used Log.v(). So it did in fact not give me incomplete result, I just wasn't able to see the full result or that it actually finished.
我可以看到您正在犯的一个系统性错误,尽管我不知道这是否是您问题的原因。
例如:
在 Java 中,数组索引从零开始,一直到
array.length - 1
。您的代码似乎在此处和其他地方跳过了第零个标记。在processFLine
中,您使用tokens[1]
在不同格式之间进行选择,结果可能会出现ArrayIndexOutOfBoundsException
。I can see one systematic mistake that you are making, though I don't know if it is the cause of your problems.
For example:
In Java, array indexes start at zero, and go up to
array.length - 1
. Your code seems to be skipping the zeroth token, here and in other places. And inprocessFLine
where you usetokens[1]
to chose between different formats, you could get anArrayIndexOutOfBoundsException
as a result.