[SOLVED] Android 7.1.1 Crash

My SpaceRocks game works great on my Android 5.0 device and according to Amazon it works on all their test devices, but I just received a new Android 7.1.1 device and it crashes with the following error: java.nio.DirectByteBuffer$MemoryRef cannot be cast to java.nio.Buffer at com.jme3.util.BufferUtils.destroyDirectBuffer (BufferUtils.java 1337)

1 Like

Okay I finally had some time and enough sunlight to setup Space Rocks in Android Studio. I also updated my com.jme3.util package with the latest stuff from the master branch and here is what LogCat spits out:

11-23 19:20:58.227 7396-7439/? E/com.jme3.app.AndroidHarnessFragment: SEVERE Exception thrown in Thread[GLThread 2599,5,main]
java.lang.ClassCastException: java.nio.DirectByteBuffer$MemoryRef cannot be cast to java.nio.Buffer
at com.jme3.util.ReflectionAllocator.destroyDirectBuffer(ReflectionAllocator.java:152)
at com.jme3.util.BufferUtils.destroyDirectBuffer(BufferUtils.java:1277)
at com.atr.jme.font.TrueTypeSfntly.createAtlasOutlined(TrueTypeSfntly.java:323)
at com.atr.jme.font.TrueTypeSfntly.createGlyphs(TrueTypeSfntly.java:261)
at com.atr.jme.font.TrueTypeBMP.getGlyphs(TrueTypeBMP.java:225)
at com.atr.jme.font.TrueTypeBMP.getGlyphs(TrueTypeBMP.java:57)
at com.atr.jme.font.TrueTypeFont.getGlyphs(TrueTypeFont.java:373)
at com.atr.jme.font.util.StringContainer.<init>(StringContainer.java:203)
at com.atr.jme.font.util.StringContainer.<init>(StringContainer.java:179)
at com.atr.jme.font.util.StringContainer.<init>(StringContainer.java:163)
at com.atr.jme.font.util.StringContainer.<init>(StringContainer.java:148)
at com.atr.jme.font.util.StringContainer.<init>(StringContainer.java:134)
at com.simsilica.lemur.component.TrueTypeTextComponent.<init>(TrueTypeTextComponent.java:54)
at com.simsilica.lemur.Label.<init>(Label.java:126)
at com.simsilica.lemur.Label.<init>(Label.java:95)
at com.simsilica.lemur.ProgressBar.<init>(ProgressBar.java:110)
at com.simsilica.lemur.ProgressBar.<init>(ProgressBar.java:71)
at com.atr.spacerocks.state.Initialize.<init>(Initialize.java:170)
at com.atr.spacerocks.SpaceRocks.simpleInitApp(SpaceRocks.java:149)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:220)
at com.jme3.app.AndroidHarnessFragment.initialize(AndroidHarnessFragment.java:556)
at com.jme3.system.android.OGLESContext.onDrawFrame(OGLESContext.java:328)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1548)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1259)

It’s being called from my true type font library which uses BufferUtils to clean up it’s textures when new ones are created. I’ll probably look into it myself when I have plenty of sunlight and some down time next if you guys haven’t already figured it out.

Sigh… android only DirectByteBuffer implementation
issue is here https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/util/ReflectionAllocator.java#L152
@Empire_Phoenix I’d need your insight on this. the “attachement” method returns a MemoryRef on android and not an Object (and definitely not a Buffer.
sdk/sources/android-25/java/nio/DirectByteBuffer.java - android_tools - Git at Google

I made a commit that might fix the issue

@Tryder Could you test please?

1 Like

I should be at a place where I can test this in a couple of days.

Try using PrimitiveAllocator instead for a first test.
The reflection allocator does a lot of ugly hacks and I kinda would suggest to avoid it if possible, try using the LWJGLBufferAllocator if you are using lwjgl.

@nehon Maybee we should make the LWJGLBufferAllocator default if lwjgl is used, and as far as I know a similar system exists for Jogl. I kinda feel like it should be time to finaly retire the reflectionhacks, especially since I think, that they do not work with java9 anyway.

[edit]
Wait we already do this according to lwjglcontext, why is the reflectionallocator even in that stacktrace?

Anyhow, for a fix for android, did you take a look at this?
https://github.com/i2p/i2p.i2p/blob/master/apps/jrobin/java/src/engine/misc/DeallocationHelper.java

Well it won’t work on android, will it?
But yeah I agree it’s a kind of hackish class and I added yet again one more hack.

I think it should, after all malloc should be accessible for native stuff even on android, and it is not much more than a wrapper around.

Strong winds, plentiful hills and perhaps a bit-o-rain tomorrow has delayed me a bit. Probably gonna be another day or so before I can test out Space Rocks with the new hack.

it’s already done for the case when you use lwjgl3.

I updated my jme 3.1 build with the new commits from master and tested it through Android Studio on my HTC U11 Life Android 7.1.1 device and it is working.

good, thanks

Thank you

Looks like I spoke too soon on this one. When I tested it I just noted that the game ran without crashing and didn’t pay attention to LogCat, but apparently the buffers are not being freed:

11-29 12:18:02.624 28755-28755/? I/com.jme3.system.JmeSystem: INFO Running on jMonkeyEngine 3.1.0-UNKNOWN
                                                               * Branch: unknown
                                                               * Git Hash: 
                                                               * Build Date: 2017-11-29
11-29 12:18:02.630 28755-28755/? I/com.jme3.system.android.OGLESContext: INFO Android Build Version: 25
11-29 12:18:02.697 28755-28796/? I/Adreno: QUALCOMM build                   : 9d71901, I9d280822bd
                                           Build Date                       : 06/28/17
                                           OpenGL ES Shader Compiler Version: XE031.14.00.04
                                           Local Branch                     : 
                                           Remote Branch                    : 
                                           Remote Branch                    : 
                                           Reconstruct Branch               : 
11-29 12:18:02.699 28755-28796/? I/Adreno: PFP: 0x005ff087, ME: 0x005ff063
11-29 12:18:02.754 28755-28795/? I/com.jme3.renderer.opengl.GLRenderer: INFO OpenGL Renderer Information
                                                                         * Vendor: Qualcomm
                                                                         * Renderer: Adreno (TM) 508
                                                                         * OpenGL Version: OpenGL ES 3.2 V@207.0 (GIT@9d71901, I9d280822bd) (Date:06/28/17)
                                                                         * GLSL Version: OpenGL ES GLSL ES 3.20
                                                                         * Profile: Compatibility
11-29 12:18:02.772 28755-28795/? W/com.jme3.asset.AssetConfig: WARNING Cannot find loader com.jme3.cursors.plugins.CursorLoader
11-29 12:18:02.807 28755-28795/? W/com.jme3.asset.AssetConfig: WARNING Cannot find loader com.jme3.scene.plugins.blender.BlenderModelLoader
11-29 12:18:02.852 28755-28795/? I/libOpenSLES: Emulating old channel mask behavior (ignoring positional mask 0x3, using default mask 0x3 based on channel count of 2)
11-29 12:18:02.853 28755-28795/? W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 1, track 44100 Hz, output 48000 Hz
11-29 12:18:02.864 28755-28795/? I/com.jme3.audio.openal.ALAudioRenderer: INFO Audio Renderer Information
                                                                           * Device: OpenAL Soft
                                                                           * Vendor: OpenAL Community
                                                                           * Renderer: OpenAL Soft
                                                                           * Version: 1.1 ALSOFT 1.16.0
                                                                           * Supported channels: 64
                                                                           * ALC extensions: ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device
                                                                           * AL extensions: AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length
11-29 12:18:02.866 28755-28795/? I/com.jme3.audio.openal.ALAudioRenderer: INFO Audio effect extension version: 1.0
11-29 12:18:02.866 28755-28795/? I/com.jme3.audio.openal.ALAudioRenderer: INFO Audio max auxiliary sends: 4
11-29 12:18:03.124 28755-28795/? W/System.err: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
11-29 12:18:03.124 28755-28795/? W/System.err: SLF4J: Defaulting to no-operation (NOP) logger implementation
11-29 12:18:03.124 28755-28795/? W/System.err: SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
11-29 12:18:03.495 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=100440 cap=100440], java.nio.DirectByteBuffer$MemoryRef@75fc054
11-29 12:18:03.590 28755-28760/? I/art: Do partial code cache collection, code=18KB, data=29KB
11-29 12:18:03.590 28755-28760/? I/art: After code cache collection, code=17KB, data=28KB
11-29 12:18:03.590 28755-28760/? I/art: Increasing code cache capacity to 128KB
11-29 12:18:03.738 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=100440 cap=100440], java.nio.DirectByteBuffer$MemoryRef@aea2031
11-29 12:18:03.933 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@264d316
11-29 12:18:04.128 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@642c497
11-29 12:18:04.336 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@a3a469
11-29 12:18:04.730 28755-28760/? I/art: Do partial code cache collection, code=42KB, data=61KB
11-29 12:18:04.731 28755-28760/? I/art: After code cache collection, code=42KB, data=61KB
11-29 12:18:04.731 28755-28760/? I/art: Increasing code cache capacity to 256KB
11-29 12:18:04.755 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@8fe505d
11-29 12:18:05.254 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@45984e0
11-29 12:18:05.539 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=401760 cap=401760], java.nio.DirectByteBuffer$MemoryRef@f407ae5
11-29 12:18:06.295 28755-28760/? I/art: Do full code cache collection, code=106KB, data=125KB
11-29 12:18:06.296 28755-28760/? I/art: Starting a blocking GC JitCodeCache
11-29 12:18:06.296 28755-28760/? I/art: After code cache collection, code=90KB, data=96KB
11-29 12:18:06.518 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=52020 cap=52020], java.nio.DirectByteBuffer$MemoryRef@704eca2
11-29 12:18:06.636 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=208080 cap=208080], java.nio.DirectByteBuffer$MemoryRef@dbe98f0
11-29 12:18:06.744 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=208080 cap=208080], java.nio.DirectByteBuffer$MemoryRef@6606e69
11-29 12:18:06.852 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=208080 cap=208080], java.nio.DirectByteBuffer$MemoryRef@6e930ee
11-29 12:18:06.960 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=208080 cap=208080], java.nio.DirectByteBuffer$MemoryRef@446898f
11-29 12:18:07.182 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=468180 cap=468180], java.nio.DirectByteBuffer$MemoryRef@38c541c
11-29 12:18:07.621 28755-28760/? I/art: Do partial code cache collection, code=107KB, data=123KB
11-29 12:18:07.622 28755-28760/? I/art: After code cache collection, code=107KB, data=123KB
11-29 12:18:07.622 28755-28760/? I/art: Increasing code cache capacity to 512KB
11-29 12:18:15.381 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=24420 cap=24420], java.nio.DirectByteBuffer$MemoryRef@2372c80
11-29 12:18:15.499 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=468180 cap=468180], java.nio.DirectByteBuffer$MemoryRef@cc36ff1
11-29 12:18:15.710 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=468180 cap=468180], java.nio.DirectByteBuffer$MemoryRef@b847d6
11-29 12:18:15.980 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=24420 cap=24420], java.nio.DirectByteBuffer$MemoryRef@d5de4f3
11-29 12:18:16.030 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=97680 cap=97680], java.nio.DirectByteBuffer$MemoryRef@3aeb5b0
11-29 12:18:16.128 28755-28795/? E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@2df2c29
11-29 12:18:16.251 28755-28760/? I/art: Do full code cache collection, code=249KB, data=248KB
11-29 12:18:16.251 28755-28760/? I/art: Starting a blocking GC JitCodeCache
11-29 12:18:16.251 28755-28760/? I/art: After code cache collection, code=195KB, data=183KB
11-29 12:18:29.642 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@b06cc10
11-29 12:18:31.916 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@871f309
11-29 12:18:36.092 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@287690e
11-29 12:18:38.165 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@47e2f2f
11-29 12:18:40.385 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@974993c
11-29 12:18:44.698 28755-28760/com.atr.spacerocks I/art: Do partial code cache collection, code=248KB, data=244KB
11-29 12:18:44.699 28755-28760/com.atr.spacerocks I/art: After code cache collection, code=245KB, data=242KB
11-29 12:18:44.699 28755-28760/com.atr.spacerocks I/art: Increasing code cache capacity to 1024KB
11-29 12:18:46.856 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=219780 cap=219780], java.nio.DirectByteBuffer$MemoryRef@5b7aec
11-29 12:18:48.904 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=390720 cap=390720], java.nio.DirectByteBuffer$MemoryRef@4ef6eb5
11-29 12:18:54.218 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=390720 cap=390720], java.nio.DirectByteBuffer$MemoryRef@9ba3c3c
11-29 12:19:01.101 28755-28795/com.atr.spacerocks E/com.jme3.util.BufferUtils: SEVERE Buffer cannot be destroyed: java.nio.DirectByteBuffer[pos=0 lim=390720 cap=390720], java.nio.DirectByteBuffer$MemoryRef@50e1dc5
11-29 12:20:25.936 28755-28755/com.atr.spacerocks W/KeyCharacterMap: Load KCM of non-default device may incur unexpected result. Device ID:4
11-29 12:20:25.940 28755-28755/com.atr.spacerocks W/com.jme3.input.android.TouchEventPool: WARNING eventPool full
11-29 12:20:25.940 28755-28755/com.atr.spacerocks W/KeyCharacterMap: Load KCM of non-default device may incur unexpected result. Device ID:4
11-29 12:20:25.942 28755-28755/com.atr.spacerocks W/com.jme3.input.android.TouchEventPool: WARNING eventPool full
11-29 12:20:25.942 28755-28755/com.atr.spacerocks W/KeyCharacterMap: Load KCM of non-default device may incur unexpected result. Device ID:4
11-29 12:20:27.301 28755-28755/com.atr.spacerocks W/IInputConnectionWrapper: reportFullscreenMode on inexistent InputConnection

arf… ok is there a way that I can test this easily?

Yeah, in jME-TTF I’m doing this:

atlas.getImage().dispose();
if (!NativeObjectManager.UNSAFE) {
    for (ByteBuffer buf : atlas.getImage().getData()) {
        BufferUtils.destroyDirectBuffer(buf);
    }
}

Where atlas is a Texture2D so I suppose just create a Texture2D instance and do that with it.

What do you think if I get rid of the BufferUtils.destroyDirectBuffer stuff and use just Image.dispose()? I don’t want this stuff hanging around in memory very long after it’s dereferenced, would that be enough?

well it would fix your issue sure. But the issue is still there in the engine.

Ok I think it’s a false issue actually.
We are in the case that the DirectByteBuffer Instance has no cleaner object here
https://chromium.googlesource.com/android_tools/+/refs/heads/master/sdk/sources/android-25/java/nio/DirectByteBuffer.java#84
So basically your image is probably not really in direct memory on android. It’ll be GCed next time the GC is ran.
From the code of our ReflectionAllocator, all steps of finding the right deallocation methods are done, and fail. IMO in that particular case there is nothing more to do than wait for the next GC.

1 Like

It fixed the issue on my android jme3 game as well (Sugar High Piggy). Thank you guys for posting this fix.

1 Like