0

I'm trying to fix what appears to be a race condition in some code using libGDX. This particular race condition crashes the JVM when it happens.

Searching through the JVM crash log, I found the following lines:

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J 1128  com.badlogic.gdx.utils.BufferUtils.copyJni([FLjava/nio/Buffer;II)V (0 bytes) @ 0x0000000002d477b0 [0x0000000002d47740+0x70]
J 1365 C2 com.badlogic.gdx.graphics.g2d.SpriteBatch.flush()V (185 bytes) @ 0x0000000002e16ad4 [0x0000000002e16940+0x194]
J 1201 C1 com.badlogic.gdx.graphics.g2d.SpriteBatch.end()V (90 bytes) @ 0x0000000002d8f2d4 [0x0000000002d8f1c0+0x114]
J 1422 C1 com.me.mygame.screens.IslandScreen.render(F)V (848 bytes) @ 0x0000000002e40624 [0x0000000002e3a4e0+0x6144]
J 1539 C1 com.badlogic.gdx.Game.render()V (25 bytes) @ 0x0000000002e6c1dc [0x0000000002e6c000+0x1dc]
j  com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop()V+698
j  com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run()V+27
v  ~StubRoutines::call_stub

One particular line involves some of my own code:

J 1422 C1 com.me.mygame.screens.IslandScreen.render(F)V (848 bytes) @ 0x0000000002e40624 [0x0000000002e3a4e0+0x6144]

Is there any way I can find what the specific line that is causing this is? If not, what can be done to debug this crash?

Matt Y
  • 192
  • 3
  • 9
  • make sure you're not instantiating, purging or flushing anything on the render method. – Hllink Jun 27 '17 at 13:52
  • Since, that method has signature "void render(float)" then look for that method in that class. You can then look for the "void end()" call to find the specific line in the render method that is making the call – Claudio Corsi Jun 27 '17 at 13:55
  • How complex is your render() method? Maybe posting that might get fresh eyes and maybe point out something you're doing incorrectly? – Peter R Jun 27 '17 at 14:28

1 Answers1

2

A stack trace in a crash log may contain both interpreted and compiled Java methods.

Interpreted methods (denoted by a small j) will also include the bytecode index (bci), e.g.

j com.me.mygame.screens.IslandScreen.render(F)V+727
                                                ^^^

Here the method render was executing the bytecode at position 727. To match this to a line number use Java decompiler like javap:

javap -c -verbose -cp CLASSPATH com.me.mygame.screens.IslandScreen

Look for LineNumberTable that maps lines in the source code to bytecode indices:

  LineNumberTable:
    line 7: 0
    line 8: 11
    ...
    line 66: 707
    line 67: 719   <-- find the nearest bci
    line 68: 731

You need the line number with the bci closest to (but not exceeding) 727. In the above example it is line 67.


Alternatively you may request JVM to execute a command right before the crash. jstack will help to generate full thread dump including line numbers.

java -XX:OnError="jstack -F %p" ...

Here -F means 'forced' mode and %p is automatically replaced by JVM process ID.

apangin
  • 92,924
  • 10
  • 193
  • 247