为了保存 3D Canvas 的快照,我通过以下方式扩展了 Canvas3D
:
class OffScreenCanvas3D extends Canvas3D {
OffScreenCanvas3D(GraphicsConfiguration graphicsConfiguration, boolean offScreen) {
super(graphicsConfiguration, offScreen);
}
public BufferedImage doRender(int width, int height) {
BufferedImage bImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
ImageComponent2D buffer = new ImageComponent2D(ImageComponent.FORMAT_RGBA, bImage);
setOffScreenBuffer(buffer);
renderOffScreenBuffer();
waitForOffScreenRendering();
bImage = getOffScreenBuffer().getImage();
setOffScreenBuffer(null);
return bImage;
}
public void postSwap() {}
}
我将其添加为宇宙 View 。主要策略如下:http://www.java2s.com/Code/Java/3D/PrintCanvas3D.htm
问题出在内存泄漏上。我的应用程序开始崩溃,当我尝试分析时,我发现 OffScreenCanvas3D
的实例占用了近 50MB,其中大部分来自两个 ArrayList
。较小的一个包含 javax.media.j3d.RenderMolecule
的实例,较大的一个包含 Object 的实例,每个实例都包含 javax.media.j3d.RenderAtomListInfo
和 javax.media .j3d.RenderMolecule
.
有人可以建议我,我做错了什么吗?
更新
我想澄清的是,即使根本没有调用doRender
(例如,启动应用程序并且没有采取更多操作),内存仍在累积。下面我将添加图像以更好地显示情况。
第一个是空闲运行应用程序的内存图。
第二个是对象占用内存的饼图。这里(a)
是为OffScreenCanvas3D
实例分配的内存,(b)
是所有其他对象占用的内存。
在下面您还可以看到 dirtyDlistPerRinfoList
和 dirtyRenderMoleculeList
占据了大部分空间。任何带有前缀 dirty 的东西都会给我一种糟糕的代码的感觉,我不知道为什么
更新2
问题似乎出在接下来的部分:
dirtyDlistPerRinfoList
对象添加到RenderBin
类的updateCanvasResource
方法中。所有 Canvas 都会发生这种情况。dirtyDlistPerRinfoList
在RenderBin
类的updateDirtyDisplayLists
方法中清除。updateDirtyDisplayLists
是从Renderer
类中的doWork
(一个可怕的 1300 行方法)为每个正在渲染的 Canvas3D 调用的。
有一件事是,离屏 Canvas 不会一直渲染,而是仅在要保存图像的那一刻渲染。是的,保存图像后,dirtyDlistPerRinfoList
中积累的所有内存都被释放。
所以主要问题是:
Data of
dirtyDlistPerRinfoList
is continuously added to canvas that's not being rendered and so the memory won't be deleted. Is this my fault of Java3D bug?
最佳答案
什么都没有。 Java 3D 应用程序至少需要 25+ MB 内存加上在 RenderMolecule 和 RenderAtomListInfo 类中存储模型所需的内存。请注意,BufferedImage 也会消耗大量内存,具体取决于其大小。不时调用 System.gc() 可能会有所帮助。 BufferedImages 并不那么容易删除。
关于Java3D离屏渲染内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13680558/