3D キャンバスのスナップショットを保存できるようにするため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() {}
}
そして、それを宇宙へのビューとして追加します。そして、主な戦略はここで説明されています: http://www.java2s.com/Code/Java/3D/PrintCanvas3D.htm
問題はメモリリークにあります。アプリがクラッシュし始め、プロファイリングを試みたところ、 のインスタンスがOffScreenCanvas3D
約50MBを占めており、その大部分が 2 つArrayList
の から来ていることがわかりました。小さい方には のインスタンスが含まれ、大きい方にはとjavax.media.j3d.RenderMolecule
をそれぞれ含む Object のインスタンスが含まれます。javax.media.j3d.RenderAtomListInfo
javax.media.j3d.RenderMolecule
私が間違っていることを誰かが私に提案できますか?
アップデート
doRender
がまったく呼び出されていない場合でも (たとえば、アプリケーションが起動され、それ以上のアクションが実行されていない場合)、メモリはまだ蓄積されていることを明確にしたいと思います。以下に、状況をよりよく示す画像を追加します。
1 つ目は、アイドル状態で実行中のアプリケーションのメモリ グラフです。
2 つ目は、オブジェクトが使用するメモリの円グラフです。(a)
のインスタンスに割り当てられるOffScreenCanvas3D
メモリは次のとおり(b)
です。 は他のすべてのオブジェクトによって占有されるメモリです。
また、下にもそれが表示されdirtyDlistPerRinfoList
、dirtyRenderMoleculeList
ほとんどのスペースを占めています。接頭辞dirtyが付いているものはすべて、悪いコードのように感じます。理由はわかりません
更新2
問題は次の部分にあるようです。
- のオブジェクトがクラスのメソッドに
dirtyDlistPerRinfoList
追加されます。これはすべてのキャンバスで発生します。updateCanvasResource
RenderBin
dirtyDlistPerRinfoList
クラスupdateDirtyDisplayLists
のメソッドでクリアされます。RenderBin
updateDirtyDisplayLists
レンダリングされているすべての Canvas3D のdoWork
クラスで (恐ろしい 1300 行のメソッド)から呼び出されます。Renderer
問題は、offScreen キャンバスが常にレンダリングされているわけではなく、画像が保存される瞬間だけであるということです。はい、画像を保存した後、蓄積されたすべてのメモリdirtyDlistPerRinfoList
が解放されます。
したがって、主な質問は次のとおりです。
のデータは、
dirtyDlistPerRinfoList
レンダリングされていないキャンバスに継続的に追加されるため、メモリは削除されません。これは Java3D バグの私のせいですか?