Just updated to the trunk and get this problem:
Is it related to this change? Do I need to do something to adjust?
http://code.google.com/p/jmonkeyengine/source/detail?r=7692
Thanks!
Exception in thread “jME Terrain Thread” java.lang.ArrayIndexOutOfBoundsException: -1
at com.jme3.util.TempVars.release(TempVars.java:171)
at com.jme3.bounding.BoundingBox.containAABB(BoundingBox.java:259)
at com.jme3.bounding.BoundingBox.computeFromPoints(BoundingBox.java:115)
at com.jme3.scene.Mesh.updateBound(Mesh.java:1095)
at com.jme3.terrain.geomipmap.LODGeomap.createMesh(LODGeomap.java:92)
at com.jme3.terrain.geomipmap.LODGeomap.createMesh(LODGeomap.java:77)
at com.jme3.terrain.geomipmap.TerrainPatch.(TerrainPatch.java:194)
at com.jme3.terrain.geomipmap.TerrainQuad.createQuadPatch(TerrainQuad.java:731)
at com.jme3.terrain.geomipmap.TerrainQuad.split(TerrainQuad.java:565)
at com.jme3.terrain.geomipmap.TerrainQuad.(TerrainQuad.java:160)
at com.jme3.terrain.geomipmap.TerrainQuad.(TerrainQuad.java:134)
at com.jme3.terrain.geomipmap.TerrainQuad.(TerrainQuad.java:130)
at com.jme3.terrain.geomipmap.TerrainGrid$UpdateQuadCache.run(TerrainGrid.java:63)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Edit: I get other similar stack traces, too:
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.ArrayIndexOutOfBoundsException: -1
at com.jme3.util.TempVars.release(TempVars.java:171)
at com.jme3.math.Matrix4f.fillFloatBuffer(Matrix4f.java:753)
at com.jme3.shader.Uniform.setValue(Uniform.java:292)
at com.jme3.renderer.RenderManager.updateUniformBindings(RenderManager.java:370)
at com.jme3.material.Material.render(Material.java:962)
at com.jme3.renderer.RenderManager.renderGeometry(RenderManager.java:656)
at com.jme3.renderer.queue.RenderQueue.renderGeometryList(RenderQueue.java:301)
at com.jme3.renderer.queue.RenderQueue.renderQueue(RenderQueue.java:357)
at com.jme3.renderer.RenderManager.renderViewPortQueues(RenderManager.java:893)
at com.jme3.renderer.RenderManager.flushQueue(RenderManager.java:849)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1125)
at com.jme3.water.WaterFilter.preFrame(WaterFilter.java:191)
at com.jme3.post.FilterPostProcessor.preFrame(FilterPostProcessor.java:328)
at com.jme3.renderer.RenderManager.renderViewPort(RenderManager.java:1099)
at com.jme3.renderer.RenderManager.render(RenderManager.java:1162)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:257)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:144)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:173)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:218)
at java.lang.Thread.run(Thread.java:662)
You apparently tried to release a TempVar instance you didn’t instantiate…
Well, er - this isn’t my code.
However, I’m looking at Matrix4f.fillFloatBuffer() and it calls TempVars.get() three lines up from where vars.release() is crashing.
It looks like the new code remy.bouquet added in r7692 is trying to manage a stack of ThreadLocal instances, and somehow it’s getting out of sync.
I don’t really know enough about this code to debug it, but I’ll keep poking at it.
Well you didnt describe where the error occurs, this might still happen (also “inside” jme) if you release a TempVar instance twice in your code. But I assume that you don’t, so we’ll look into it
I checked, and I don’t have any direct references to TempVars in my code.
I do have one other stack trace that includes my code (see below).
I have a Quad core processor, and am running both TerrainGrid and my own executor to optimize batches in the background as tasks on a single thread.
this just started since I updated from the trunk tonight, which included the commit I referenced above, so I don’t think it’s something I’m doing.
SEVERE: exception:
java.lang.ArrayIndexOutOfBoundsException: -1
at com.jme3.util.TempVars.release(TempVars.java:171)
at com.jme3.scene.Spatial.checkDoTransformUpdate(Spatial.java:473)
at com.jme3.scene.Geometry.computeWorldMatrix(Geometry.java:278)
at jme3tools.optimize.GeometryBatchFactory.mergeGeometries(GeometryBatchFactory.java:162)
at jme3tools.optimize.GeometryBatchFactory.makeBatches(GeometryBatchFactory.java:286)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:337)
at jme3tools.optimize.GeometryBatchFactory.optimize(GeometryBatchFactory.java:321)
at com.spaceship.bushcraft.scenery.BatchNodePage.load(BatchNodePage.java:47)
at com.spaceship.bushcraft.scenery.ThreadedPageLoader$LoadTask.call(ThreadedPageLoader.java:96)
at com.spaceship.bushcraft.scenery.ThreadedPageLoader$LoadTask.call(ThreadedPageLoader.java:87)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
I reverted to r7691 and the problem is gone, so I’ll continue developing with that version for now.
Just for kicks, I tried a few things because I’d really like to update to get anthyon’s recent fix (r7738 Fix: calculating localTranslation after gridChange).
I tried making sure I’m using only jars from the dist/ folder of my local jme3 build, on the thought that combining out of date jars from the last JMP nightly update (which was several days ago due to the unrelated problem) and the engine jar from my local project could be causing problems. Alas, I still get the exceptions.
I also moved my terrain batch creation back onto the main render loop thread, which causes horrible stutters and does not eliminate these exceptions.
Switching whether bullet uses BulletAppState.ThreadingType.PARALLEL or BulletAppState.ThreadingType.SEQUENTIAL did not help either.
I see the same exceptions running TerrainGridTest and TerrainFractalGridTest out of the local jme3 build, with none of my code present, though less frequent.
I don’t (at least not in how long I played around with it) get this problem in many of the other test apps.
Is it possible the problem has to do with how TerrainGrid is using TempVars now that TempVars has been changed?
I have the same errors. I use BatchFactory to optimize geometries in background (multi-threaded), and sometimes, it crashes this same way.
Just to state: I haven’t introduced TempVars in TerrainGrid, it should lie deeper in the call hierarchy, but I have this very same exception popping up, when starting my tests
Actually… looking at TempVars… it has some issues with the latest changes. I think @nehon has some internal reworking yet to do.
Note: if you build from SVN then you can probably just revert that single file to the previous version. I’m pretty sure the signature did not change.
Not that simple, unfortunately. It looks like he added a release() method and calls to it from many different places. The engine won’t build with just that file reverted.
Ok. Sorry.
I’ve sent my notes to the relevant places I could think of. I’d fix it myself but I’m not in a position to test it properly. Hopefully it can get resolved soon.
I think I have at least a brute force solution that seems to have fixed the problem or reduced the frequency to the point I don’t see it anymore in limited testing.
I added synchronized(TempVars.class) {…} blocks around the code in
public final void release()
and in
public static TempVars get()
It looks to me like the usage of the static variable ‘stackLevel’ by the non-static release() method is not thread-safe.
I await someone with more familiarity with the subject to submit a more correct fix, if there is one.
Thanks!
synchronized is definitely the two-ton sledge hammer approach in this case. It would be better and probably faster (as a temporary fix) just to comment out all of the code in get() and release() and just return a new TempVars in get() every time. On deskop JVMs, I’d be very much surprised if it were that much slower.
The real solution is to move the stack and its indexes into an inner class that is kept in the thread local (instead of just the array). There is an opportunity here to simplify the code as well. I’ve sent all of this information to the author but I do not know when the fix will come exactly.
Oddly enough, when I change the code as you suggest, my frame rate drops (in my demo code) from a smooth average of around 130fps to a stuttering mess never getting over about 80. I have no idea why.
I can’t really tell if the synchronized fix is slower than the code without the synchronized blocks (I’m sure it is), but without the fix it’s so unstable I can’t use it.
Anyways, I’m satisfied with this for now until an official fix is committed and wanted to make sure any others who are blocked by this to have a way to work around it too.
Thanks for your time!
Fixed in SVN
mattias said:
Oddly enough, when I change the code as you suggest, my frame rate drops (in my demo code) from a smooth average of around 130fps to a stuttering mess never getting over about 80. I have no idea why.
I can't really tell if the synchronized fix is slower than the code without the synchronized blocks (I'm sure it is), but without the fix it's so unstable I can't use it.
Anyways, I'm satisfied with this for now until an official fix is committed and wanted to make sure any others who are blocked by this to have a way to work around it too.
Thanks for your time!
Yeah, I forgot how big a single instance of TempVars is. I keep thinking of where they are used... frequently only a handful of the fields are used.
Anyway... as said, it's fixed now. :)
I can confirm the fix works, thanks!