Mordag
August 28, 2015, 1:16am
41
Thank you for the explanation.
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode):
"Timer-0" #25 prio=5 os_prio=0 tid=0x0000000033dd5800 nid=0x3138 in Object.wait() [0x000000001b8af000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Unknown Source)
- locked <0x00000000e4290ca0> (a java.util.TaskQueue)
at java.util.TimerThread.run(Unknown Source)
"DestroyJavaVM" #22 prio=5 os_prio=0 tid=0x0000000002fa0800 nid=0x1aa0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"TimerQueue" #20 daemon prio=5 os_prio=0 tid=0x000000001b11a800 nid=0x235c waiting on condition [0x0000000020f9f000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000812f8468> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(Unknown Source)
at java.util.concurrent.DelayQueue.take(Unknown Source)
at javax.swing.TimerQueue.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
"D3D Screen Updater" #19 daemon prio=7 os_prio=1 tid=0x000000001b10e800 nid=0x2430 in Object.wait() [0x0000000020e9f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at sun.java2d.d3d.D3DScreenUpdateManager.run(Unknown Source)
- locked <0x00000000812f86d8> (a java.lang.Object)
at java.lang.Thread.run(Unknown Source)
"AWT-Windows" #13 daemon prio=6 os_prio=0 tid=0x000000001aecc000 nid=0x3650 runnable [0x000000001b9ae000]
java.lang.Thread.State: RUNNABLE
at sun.awt.windows.WToolkit.eventLoop(Native Method)
at sun.awt.windows.WToolkit.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
"Java2D Disposer" #11 daemon prio=10 os_prio=2 tid=0x000000001aedc000 nid=0x1200 in Object.wait() [0x000000001b7af000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x00000000812f7f20> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at sun.java2d.Disposer.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x000000001a25e800 nid=0x3318 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C1 CompilerThread3" #9 daemon prio=9 os_prio=2 tid=0x000000001a1d4800 nid=0x27dc waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001a1cf000 nid=0x3d0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001a1c8800 nid=0x1390 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001a1c4800 nid=0x213c waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001a1c3000 nid=0x3104 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001a1c2000 nid=0x988 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x0000000003098800 nid=0x2d4c in Object.wait() [0x000000001a08e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
- locked <0x0000000081306760> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(Unknown Source)
at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)
"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000003092000 nid=0x2bd8 in Object.wait() [0x0000000019f8f000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
- locked <0x000000008135b028> (a java.lang.ref.Reference$Lock)
"VM Thread" os_prio=2 tid=0x00000000180c9000 nid=0xe8 runnable
"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x0000000002fb6800 nid=0x1274 runnable
"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002fb8000 nid=0x17f8 runnable
"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002fb9800 nid=0x2a54 runnable
"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002fbc000 nid=0x19f4 runnable
"GC task thread#4 (ParallelGC)" os_prio=0 tid=0x0000000002fbd000 nid=0x199c runnable
"GC task thread#5 (ParallelGC)" os_prio=0 tid=0x0000000002fbe800 nid=0x2c50 runnable
"GC task thread#6 (ParallelGC)" os_prio=0 tid=0x0000000002fc2800 nid=0x3414 runnable
"GC task thread#7 (ParallelGC)" os_prio=0 tid=0x0000000002fc3800 nid=0x2cec runnable
"VM Periodic Task Thread" os_prio=2 tid=0x000000001a272000 nid=0x1734 waiting on condition
JNI global references: 453
Heap
PSYoungGen total 227840K, used 165435K [0x00000000d5980000, 0x00000000ea680000, 0x0000000100000000)
eden space 143872K, 65% used [0x00000000d5980000,0x00000000db6376e0,0x00000000de600000)
from space 83968K, 83% used [0x00000000e4280000,0x00000000e8757880,0x00000000e9480000)
to space 94720K, 0% used [0x00000000de600000,0x00000000de600000,0x00000000e4280000)
ParOldGen total 161792K, used 101889K [0x0000000080c00000, 0x000000008aa00000, 0x00000000d5980000)
object space 161792K, 62% used [0x0000000080c00000,0x0000000086f804e8,0x000000008aa00000)
Metaspace used 23089K, capacity 23405K, committed 23808K, reserved 1071104K
class space used 2616K, capacity 2724K, committed 2816K, reserved 1048576K
Well the good thing is, I cannot see the memory tracking anywhere in there anymore
Pssoble causes could be:
the timer
all other threads are daemons or necessary for the vm internals as far as I can see.
pspeed
August 28, 2015, 6:12am
43
Does the basic starter app when you create a new app do this also?
If not, you could start from there and see what you have to add from your game to cause the hanging. Especially if you do anything with holding references to an AWT/Swing window or other Java2D resources.
All of my 3.1 based games close correctly so my guess is that the basic game template will also close correctly.
Well the timer thread is the only non-system, non-daemon thread in the entire list.
Do you have a timer task scheduled to be executed at a later time?
Mordag
August 28, 2015, 4:20pm
45
You mean without loading anything else? The only thing I found is: If I am in the start menu of my application (itās my custom state and the first state of my project), I have no problems to close the app completely. Which means there anything in the game-state which causes this behaviour, but I donāt see which part could cause this problem. I init my GUI, several objects and their position based on a forced-based layout and init my data basis (like metadata for a market simulation). Nothing which could case something like this, I would say. There have to be anything in jme 3.1 which have been changed which is causing this, 3.0 has no problems executing this.
No I havenāt used a timer to schedule any task.
pspeed
August 28, 2015, 7:17pm
46
I mean exactly what I said. Create a new project, ie: a new basic starter app using the basic game template. But youāve already confirmed that it works with a simplified app so there is no need to do that now. There is something your code is doing that is causing this hanging.
Yes, lots of things have changed in 3.1 that might be exploiting this issue in your app now. Now that you know that itās something your code is doing then you can try to isolate it. Something in 3.0 was apparently hiding this somehow.
I mean, it could be a bug in 3.1 but itās hard to say what it is and even harder to find when none of our apps exhibit the issue.
Mordag
August 29, 2015, 3:10am
47
Iāve found a possible clue. It seems like that Nifty is responsible for the hanging. My guess would be that the batch renderer is somehow the core problem (because thatās the biggest part of nifty which has been changed, as far as I know). Well, if I reduced the amount of elements on my HUD screen I had no problems to close the app. After slightly increasing the amount, the problem appeared again.
pspeed
August 29, 2015, 7:03am
48
Is it the number of elements or perhaps some specific elements?
Mordag
August 29, 2015, 12:48pm
49
Itās the number of elements, I am sure of it. Iāve tested it with a for loop and depending on the amount of iterations I have problems to exit the app or not.
Mordag
August 30, 2015, 2:11pm
50
Finally Iāve got a test case with basic game template. This will make your game unable to close.:
package mygame;
import com.jme3.app.SimpleApplication;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.renderer.RenderManager;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.builder.LayerBuilder;
import de.lessvoid.nifty.builder.PanelBuilder;
import de.lessvoid.nifty.builder.ScreenBuilder;
import de.lessvoid.nifty.controls.button.builder.ButtonBuilder;
import de.lessvoid.nifty.controls.label.builder.LabelBuilder;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.render.batch.BatchRenderConfiguration;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.tools.Color;
public class Main extends SimpleApplication implements ScreenController {
private Nifty nifty;
private NiftyJmeDisplay niftyDisplay;
public static void main(String[] args) {
Main app = new Main();
app.start();
}
@Override
public void simpleInitApp() {
inputManager.deleteMapping(SimpleApplication.INPUT_MAPPING_EXIT);
niftyDisplay = NiftyJmeDisplay.newNiftyJmeDisplay(
this.assetManager,
this.inputManager,
this.audioRenderer,
this.guiViewPort,
new BatchRenderConfiguration());
nifty = niftyDisplay.getNifty();
viewPort = renderManager.createPostView("Test", guiViewPort.getCamera().clone());
viewPort.addProcessor(niftyDisplay);
nifty.isIgnoreKeyboardEvents();
nifty.setDebugOptionPanelColors(false);
createHUDScreen("TEST");
initControls();
for (int i = 0; i < 500; i++) {
//both elements alone will break the game; haven't check all possible elements yet
ButtonBuilder createButton = new ButtonBuilder("");
createButton.id("Test-Content" + i);
createButton.height("10%");
createButton.width("10%");
createButton.valignCenter();
createButton.alignCenter();
createButton.focusable(false);
createButton.style("");
createButton.backgroundColor(Color.WHITE);
createButton.interactOnClick("windowControl(test)");
createButton.childLayoutCenter();
createButton.visibleToMouse(true);
Element panelT = createButton.build(nifty, nifty.getScreen("TEST"), nifty.getScreen("TEST").findElementById("TEST-Layer0"));
// LabelBuilder createLabel = new LabelBuilder();
// createLabel.id("Test-Label" + i);
// createLabel.text("Bla");
// createLabel.textHAlignCenter();
// createLabel.textVAlignCenter();
// createLabel.alignCenter();
// createLabel.valignCenter();
// createLabel.height(100 + "%");
// createLabel.width(100 + "%");
// createLabel.wrap(true);
// createLabel.font("aurulent-sans-16.fnt");
// createLabel.build(nifty, nifty.getScreen("TEST"), nifty.getScreen("TEST").findElementById("TEST-Layer0"));
}
nifty.gotoScreen("TEST");
inputManager.setCursorVisible(true);
}
private void createHUDScreen(String screenID) {
ScreenBuilder screenBuilder = new ScreenBuilder(screenID);
screenBuilder.controller(this);
LayerBuilder layer0 = new LayerBuilder(screenID + "-Layer0");
layer0.childLayoutCenter();
screenBuilder.layer(layer0);
LayerBuilder layer1 = new LayerBuilder(screenID + "-Layer1");
layer1.childLayoutCenter();
screenBuilder.layer(layer1);
LayerBuilder layer2 = new LayerBuilder(screenID + "-Layer2");
layer2.childLayoutAbsolute();
screenBuilder.layer(layer2);
LayerBuilder layer3 = new LayerBuilder(screenID + "-Layer3");
layer3.childLayoutAbsolute();
screenBuilder.layer(layer3);
nifty.addScreen(screenID, screenBuilder.build(nifty));
}
private void initControls() {
nifty.loadStyleFile("nifty-default-styles.xml");
nifty.loadControlFile("nifty-default-controls.xml");
}
@Override
public void simpleUpdate(float tpf) {
//TODO: add update code
}
@Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
@Override
public void bind(Nifty nifty, Screen screen) {
}
@Override
public void onStartScreen() {
}
@Override
public void onEndScreen() {
}
}
@pspeed Can you verify this on your side?
pspeed
August 31, 2015, 1:04am
51
Your test case looks very nice for someone to help find what is happeningā¦ but since I abandoned nifty like over 3 years ago, Iām personally loathe to help debug it or to setup a project that uses it. I just donāt have the bandwidth right now.
Your test case should be perfect for someone who uses nifty, though.
Mordag
August 31, 2015, 9:33pm
52
Ok thanks ^^ It also seems I am not the only one with this problem. I have created an issue on the nifty github page, but I donāt think this will be fixed anytime soon. Which means jme 3.1 will be a no-go until this bug is fixed (it seems that 1.4.x of nifty is way more bugged than 1.3.x).
It seems that nifty is keeping two timer threads up after destruction, which prevent the application from closing.
n3cr0
September 1, 2015, 5:38am
54
I have to say, I do not use the nifty gui and I have the exact same problem at the moment, the game application never close after exiting.
Same thread 4, the āRawInputEventQueuā
pspeed
September 1, 2015, 5:56am
55
Follow the instructions above for running from the command line and getting a thread dump after the app āhangsā. Some non-daemon thread is keeping your app open. Daemon threads wonāt do it.
Mega Hack:
in application:
@override
OnDestroy{
System.exit(0);
}
Unclean as fuck, but will terminate at least.
2 Likes
I seem to have an issue in cleanup code.
When I try to remove a FilterPostProcessor with samples from the viewport when I am exiting an application, I will get an exception. I will provide the stack trace once I get back home.
It happens sometime in game as well.
I added the issue report here:
opened 06:52PM - 04 Sep 15 UTC
closed 09:57PM - 17 Jan 18 UTC
Cross referencing this from the Nifty GUI issue tracker:
nifty-gui/nifty-gui#365
Seems to happen due to some timer threads (Timer-0, etc) staying alive even...
bug
Just curious: what do folks use if you arenāt using Nifty anymore?
pspeed
September 5, 2015, 3:53am
60
In order of my preference:
-Lemur (because I wrote it and I write 3D GUIs and itās directly JME scene graph components) http://hub.jmonkeyengine.org/c/user-code-projects/lemur
-JavaFX (if I didnāt have Lemur this is probably what Iād use) I donāt have the link handy but you can search the forum.
-tonegodGUI - similarly search the forum