[iOS] Multiple issues (and solutions/workarounds) trying to run jme3 app

Hi,

I’m thinking on exporting my current project to iOS also, so I first tried to build the default BasicGame for iOS. I followed the instructions at ios :: jMonkeyEngine Docs and also checked some related hub links like

and after having passed through all known issues I’ve read about in the links, I finally was able to compile it.

I tried to run it using the simulator and I got the following exception:

2021-02-18 03:01:45.283371+0100 jme-ios[21015:450868] Could not create new iOS Harness object
java/lang/AssertionError: java.lang.ClassNotFoundException: sun/nio/fs/MacOSXFileSystemProvider
  at sun/nio/fs/DefaultFileSystemProvider$1.run (line 49)
  at sun/nio/fs/DefaultFileSystemProvider$1.run (line 43)
  at java/security/AccessController.doPrivileged (native)
  at sun/nio/fs/DefaultFileSystemProvider.createProvider (line 42)
  at sun/nio/fs/DefaultFileSystemProvider.create (line 72)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.getDefaultProvider (line 108)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.access$000 (line 89)
  at java/nio/file/FileSystems$DefaultFileSystemHolder$1.run (line 98)
  at java/nio/file/FileSystems$DefaultFileSystemHolder$1.run (line 96)
  at java/security/AccessController.doPrivileged (native)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.defaultFileSystem (line 95)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.<clinit> (line 90)
  at java/nio/file/FileSystems.getDefault (line 176)
  at sun/util/calendar/ZoneInfoFile$1.run (line 483)
  at sun/util/calendar/ZoneInfoFile$1.run (line 478)
  at java/security/AccessController.doPrivileged (native)
  at sun/util/calendar/ZoneInfoFile.<clinit> (line 477)
  at sun/util/calendar/ZoneInfo.getTimeZone (line 663)
  at java/util/TimeZone.getTimeZone (line 566)
  at java/util/TimeZone.setDefaultZone (line 663)
  at java/util/TimeZone.getDefaultRef (line 630)
  at java/util/TimeZone.getDefault (line 617)
  at java/text/SimpleDateFormat.initializeCalendar (line 682)
  at java/text/SimpleDateFormat.<init> (line 619)
  at java/text/DateFormat.get (line 772)
  at java/text/DateFormat.getTimeInstance (line 472)
  at java/text/MessageFormat.makeFormat (line 1490)
  at java/text/MessageFormat.applyPattern (line 479)
  at java/text/MessageFormat.<init> (line 363)
  at com/jme3/util/JmeFormatter.<init> (line 56)
  at com/jme3/system/ios/IosLogHandler.<init> (line 45)
  at com/jme3/system/ios/JmeIosSystem.initialize (line 106)
  at com/jme3/system/ios/JmeIosSystem.newContext (line 82)
  at com/jme3/system/JmeSystem.newContext (line 159)
  at com/jme3/app/LegacyApplication.start (line 461)
  at com/jme3/app/LegacyApplication.start (line 424)
  at com/jme3/app/SimpleApplication.start (line 127)
  at JmeAppHarness.<init> (unknown line)
caused by: java/lang/ClassNotFoundException: sun/nio/fs/MacOSXFileSystemProvider
  at java/lang/Class.forName0 (native)
  at java/lang/Class.forName (line 278)
  at sun/nio/fs/DefaultFileSystemProvider$1.run (line 47)
  at sun/nio/fs/DefaultFileSystemProvider$1.run (line 43)
  at java/security/AccessController.doPrivileged (native)
  at sun/nio/fs/DefaultFileSystemProvider.createProvider (line 42)
  at sun/nio/fs/DefaultFileSystemProvider.create (line 72)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.getDefaultProvider (line 108)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.access$000 (line 89)
  at java/nio/file/FileSystems$DefaultFileSystemHolder$1.run (line 98)
  at java/nio/file/FileSystems$DefaultFileSystemHolder$1.run (line 96)
  at java/security/AccessController.doPrivileged (native)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.defaultFileSystem (line 95)
  at java/nio/file/FileSystems$DefaultFileSystemHolder.<clinit> (line 90)
  at java/nio/file/FileSystems.getDefault (line 176)
  at sun/util/calendar/ZoneInfoFile$1.run (line 483)
  at sun/util/calendar/ZoneInfoFile$1.run (line 478)
  at java/security/AccessController.doPrivileged (native)
  at sun/util/calendar/ZoneInfoFile.<clinit> (line 477)
  at sun/util/calendar/ZoneInfo.getTimeZone (line 663)
  at java/util/TimeZone.getTimeZone (line 566)
  at java/util/TimeZone.setDefaultZone (line 663)
  at java/util/TimeZone.getDefaultRef (line 630)
  at java/util/TimeZone.getDefault (line 617)
  at java/text/SimpleDateFormat.initializeCalendar (line 682)
  at java/text/SimpleDateFormat.<init> (line 619)
  at java/text/DateFormat.get (line 772)
  at java/text/DateFormat.getTimeInstance (line 472)
  at java/text/MessageFormat.makeFormat (line 1490)
  at java/text/MessageFormat.applyPattern (line 479)
  at java/text/MessageFormat.<init> (line 363)
  at com/jme3/util/JmeFormatter.<init> (line 56)
  at com/jme3/system/ios/IosLogHandler.<init> (line 45)
  at com/jme3/system/ios/JmeIosSystem.initialize (line 106)
  at com/jme3/system/ios/JmeIosSystem.newContext (line 82)
  at com/jme3/system/JmeSystem.newContext (line 159)
  at com/jme3/app/LegacyApplication.start (line 461)
  at com/jme3/app/LegacyApplication.start (line 424)
  at com/jme3/app/SimpleApplication.start (line 127)
  at JmeAppHarness.<init> (unknown line)

I tried both 3.2.4 and 3.3.2-preview1 with the exact same result (when using 3.3.2 I had to force it to use java8 bytecode because otherwise I would get a link issue v55 vs v52).

The class sun.nio.fs.MacOSXFileSystemProvider is from the jdk itself, so I double checked default project configuration and both link to proper avian path at private.properties:ios.avian.path :

(3.2.4) /Users/user/Library/Application\ Support/jmonkeyplatform/v3.2.4-stable-sdk1/avian-openjdk
(3.3.2) /Users/user/Library/Application\ Support/jmonkeyplatform/dev/avian-openjdk

In both folders the class exists at classpath/sun/nio/fs/MacOSXFileSystemProvider.class

I don’t know how to continue from here. Any help is appreciated

I’m running OSX Catalina (10.15.3) and Xcode 11.3.1

Thanks

1 Like

OK, I finally found out, it was proguard changing the class which is loaded though reflection. There’s a proguard keep line defined in ios.properties but for some weird reason it’s ignored, so I added it directly to avian proguard file instead

I’m now facing other issues I’ll post here also just in case it’s usefull for anyone else

EDIT:

I’m getting the following error:

**Loaded Common/MatDefs/Misc/Unshaded.j3md with J3MLoader**
**dyld: lazy symbol binding failed: Symbol not found: _objc_alloc_init**
**Referenced from: /Users/user/Library/Developer/CoreSimulator/Devices/13F125B3-1E0D-4DC3-BD04-B5F31D111A95/data/Containers/Bundle/Application/74B1660E-D315-4C7F-9140-3BAFDB4E058B/jme-ios.app/jme-ios**
**Expected in: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib**
**dyld: Symbol not found: _objc_alloc_init**
**Referenced from: /Users/user/Library/Developer/CoreSimulator/Devices/13F125B3-1E0D-4DC3-BD04-B5F31D111A95/data/Containers/Bundle/Application/74B1660E-D315-4C7F-9140-3BAFDB4E058B/jme-ios.app/jme-ios**
**Expected in: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 12.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libobjc.A.dylib**

At least in my case it was caused by using a simulator with ios version 12.0 or lower. Solved by just using a newer release. 12.4 or newer worked flawlessly, well… at least it rendered the blue cube

4 Likes

Trying with 3.3.2 I’m getting the following exception:

2021-02-18 16:41:40.829888+0100 jme-ios[35127:927343] Could not create new iOS Harness object
java/lang/NoSuchMethodError: clear ()Ljava/nio/ByteBuffer; not found in java/nio/ByteBuffer
  at com/jme3/util/BufferUtils.createByteBuffer (line 990)
  at com/jme3/renderer/opengl/GLRenderer.<init> (line 82)
  at com/jme3/system/ios/IGLESContext.create (line 164)
  at com/jme3/app/LegacyApplication.start (line 463)
  at com/jme3/app/LegacyApplication.start (line 424)
  at com/jme3/app/SimpleApplication.start (line 127)
  at JmeAppHarness.<init> (unknown line)

Looks really similar to Exception in thread "main" java.lang.NoSuchMethodError: java.nio.ByteBuffer.flip()Ljava/nio/ByteBuffer - Stack Overflow and Is anyone familiar with Ant? I need help! which is usually solved by forcing compilation to use same java version using parameters source=1.8, target=1.8 and/or release=8 (depending on the jdk version you’re using) but ios uses avian so the issue may be related to it… I’ve double checked bytecode version of all .class generated and they all are 1.7 (avian stuff) and 1.8 (all other code and jme3.3.2 itself)

Any ideas?

EDIT:

I fixed it by recompiling jme3 from master using java8 and it worked. Also tried with java11 setting at common.gradle:

compileJava {
    options.release = 8
}

which also worked

@sgold Is jme3 being built using java >=9 ? Changing this should fix this ios issue

Maybe other option would be updating avian to java11 if possible (or any other jvm) but for sure it’s much more complex

1 Like

According to my read of the YAML, JME v3.3.2 should’ve been deployed from a JDK 8 build:

2 Likes

Thanks for your answer. I just replaced SDK included jme3-core with 3.3.2 at Release jMonkeyEngine 3.3.2-stable · jMonkeyEngine/jmonkeyengine · GitHub and it worked, so I assume the SDK is recompiling the engine itself (using java11) instead of including prebuilt libraries

2 Likes

That’s probably it. I’ll recategorize this as an SDK topic.

2 Likes

OK, let’s hope someone experienced with the SDK internals knows and can fix it :wink:

In the meanwhile, I’m facing other issue with jme+ios. I’m trying some more complex stuff like creating a whole scene and I’m getting the following exception:

java/lang/OutOfMemoryError: Direct buffer memory
  at java/nio/Bits.reserveMemory (line 658)
  at java/nio/DirectByteBuffer.<init> (line 123)
  at java/nio/ByteBuffer.allocateDirect (line 306)
  at com/jme3/util/ReflectionAllocator.allocate (line 178)
  at com/jme3/util/BufferUtils.createByteBuffer (line 989)
  at com/jme3/texture/plugins/HDRLoader.load (line 299)
  at com/jme3/texture/plugins/HDRLoader.load (line 324)
  at com/jme3/asset/DesktopAssetManager.loadLocatedAsset (line 260)
  at com/jme3/asset/DesktopAssetManager.loadAsset (line 374)
  at com/jme3/asset/DesktopAssetManager.loadTexture (line 391)
  at com/jme3/util/SkyFactory.createSky (line 291)
  at mygame/Main.simpleInitApp (line 77)
  at com/jme3/app/SimpleApplication.initialize (line 239)
  at com/jme3/system/ios/IGLESContext.create (line 175)
  at com/jme3/app/LegacyApplication.start (line 463)
  at com/jme3/app/LegacyApplication.start (line 424)
  at com/jme3/app/SimpleApplication.start (line 127)
  at JmeAppHarness.<init> (unknown line)

The app is crashing in the first step in which I’m trying to create a sky using hdr textures from jme3-testdata package as follows:

Spatial sky = SkyFactory.createSky(assetManager, "Textures/Sky/Path.hdr", SkyFactory.EnvMapType.EquirectMap);

It’s happening in the simulator (I’ve not had the opportunity to test a physical device)

3 Likes

Have you tried increasing the amount of direct buffer memory?

On desktop systems, I do this by passing an argument such as -XX:MaxDirectMemorySize=1g to the JVM instance.

I thought about it just before reading your comment. In fact I modified jmeAppDelegate.m to pass the memory parameters Xmx1024m, Xms256m and XX:MaxDirectMemorySize=1024m and it failed in the exact same way, maybe avian doesn’t support it or it’s because of the simulator :thinking:

EDIT:

I managed to change direct memory through reflection:

    try
    {
        Class c = Class.forName("java.nio.Bits");
        Field maxMemory = c.getDeclaredField("maxMemory");
        maxMemory.setAccessible(true);
        Field reservedMemory = c.getDeclaredField("reservedMemory");
        reservedMemory.setAccessible(true);
        synchronized (c) {
            maxMemory.setLong(null, 1610612736L); //1.5GB
            Long maxMemoryValue = (Long)maxMemory.get(null);
            Long reservedMemoryValueLong=0L;
            if(reservedMemory.get(null) instanceof java.util.concurrent.atomic.AtomicLong)
            {
                java.util.concurrent.atomic.AtomicLong reservedMemoryValue = (java.util.concurrent.atomic.AtomicLong)reservedMemory.get(null);
                reservedMemoryValueLong=reservedMemoryValue.longValue();
            }
            else
            {
                reservedMemoryValueLong=(Long)reservedMemory.get(null);
            }
            
            System.out.println("Memory: " + reservedMemoryValueLong + " / " + maxMemoryValue );
        }
    } catch (ClassNotFoundException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NoSuchFieldException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalArgumentException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
    }

And now it doesn’t fail because of OutOfMemory

2 Likes

I was having an exception in android (cannot remember what it was exactly , I can paste the stackTrace to you later ) when trying to add a sky map using the default code , so I have changed the depth of rendering & it works fine .

Hi @Pavl_G! I tried the exact same code on android and worked for me, so it shouldn’t be related with my exception. Sounds weird to me that changing the material render state fixed your issue. Please post the stacktrace when possible, I’m curious about that. Also, what jme3 release are you using?

1 Like

Hi @joliver82

Not related to the issue, but curious if JME audio works on iOS?

1 Like

I am curious too , because it’s not working on android , too.

I think for android, you should use jme3-android-native.jar 3.3.0-alpha2 or below. (more details here)

Edit: for android issues you may want to create a new topic. :slightly_smiling_face:

2 Likes

I’ve not tested sound on ios still but according to this post it’s supposed to be fixed either using ios-data from @revv fork or using 3.3 (which already includes the required changes).

About android, as @Ali_RS said you need to downgrade your android native

2 Likes

Hi again!

I’m trying to run a simple app on a physical device because gl support in simulator is just crap. Xcode requires the app to be signed and I set up a team linking xcode to my apple ID and I’m getting the following error:

Command CodeSign failed with a nonzero exit code

Being more specific, it’s outputting “errSecInternalComponent”

I’ve search and most people had the same issue and was fixed just by locking the login keystore and unlocking it on demand when xcode tried to sign an app, removing sign keys so xcode creates a new one and even just by rebooting. None of those worked for me

I’ve also read that something inside the app itself could make the codesign binary fail, so I tried to build a default iphone app created from scratch with the same result.

I know this is not strictly jme3 related but I appreciate any help

Thanks

EDIT:

I just found the issue is caused because apple ca expired: WWDR Intermediate Certificate Expiration - Support - Apple Developer if using xcode <=11.4.0 (my case) you need to manually download and install new WWDR certificates

Hi, sorry for late reply. Did you manage to get it working and deploy to app store?

Hi @GTWhite!

I’m still on it. My app is not finished so I’m not planning to publish it to app store yet but I wanted to check current ios support and the possibility to publish it also there, but it’s being a real pain :frowning:

Now I found other issue. If using any filter the screen rendered black without any information on xcode log.

Then I realized the ios gl wrapper had the same issue android gl had before, glTexImage2D was using format as internal format:

@Override
public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) {
    JmeIosGLES.glTexImage2D(target, level, format, width, height, 0, format, type, data);
}

So I fixed it as follows:

@Override
public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) {
    JmeIosGLES.glTexImage2D(target, level, internalFormat, width, height, 0, format, type, data);
}

Now I’m getting the following exception:

java/lang/IllegalStateException: Framebuffer has erronous attachment.
  at com/jme3/renderer/opengl/GLRenderer.checkFrameBufferError (line 1704)
  at com/jme3/renderer/opengl/GLRenderer.updateFrameBuffer (line 1877)
  at com/jme3/renderer/opengl/GLRenderer.setFrameBuffer (line 2018)
  at com/jme3/renderer/RenderManager.renderViewPort (line 1082)
  at com/jme3/renderer/RenderManager.render (line 1158)
  at com/jme3/app/SimpleApplication.update (line 272)
  at JmeAppHarness.appDraw (unknown line)

I thought it could be because jme3 uses RGB16F format if float textures are supported and maybe apple hardware failed on that although the extension was exposed so I tried forcing it to RGB8: fpp.setFrameBufferFormat(Image.Format.RGB8) with no luck.

I’ve tried to use the GLDebug class by enabling GraphicsDebug in AppSettings but the app just dies, so I added some manual prints at related methods.

The texture is being created as internalFormat=GL_RGB16F, format=GL_RGB and type=GL_HALF_FLOAT_OES which should be ok if the extension is available but glTexImage2D is giving error GL_INVALID_OPERATION as if the format was wrong

Have you used filters in any of your apps?

** Edited the whole post to give more details

EDIT2:

I’ve been working deeper into this, it seems that there’s a big difference between ES2 and ES3 (and also desktop GL) in glTexImage2d: glTexImage2D gles2 vs glTexImage2d gles3 in the first case it specifies “internalformat must match format. No conversion between formats is supported during texture image processing. type may be used as a hint to specify how much precision is desired, but a GL implementation may choose to store the texture array at any internal resolution it chooses.” So it was correct for iphone as it’s using gles2. Reverting my change and checking why it’s being rendered black :thinking:

Also, iOS insists on power of 2 images. Don’t know if you have come across that?

Hi, I think it’s also worth mentioning that Apple have deprecated OpenGL from iOS 12 and they are no longer including the JVM framework in Xcode 12, so you need to use Xcode 11 for now and you have to target iOS 13 or below. They want us to migrate to Metal kit instead which I am currently looking into

Also, OpenAL is deprecated on iOS

And, Avian is currently not being maintained so the template for iOS as a whole needs to be revisited. Don’t suppose you have got time on your hands?? I haven’t got much but I’m working on it.