My experience with jME on iOS

This is the logger results when I am running my app on IOS device. This section is when I’m registering the network message classes for serialization.

Registered class[-42]:class com.jme3.network.message.DisconnectMessage to:com.jme3.network.message.DisconnectMessage$DisconnectSerializer(at)1eaa9af6
Registered class[-44]:class com.jme3.network.message.ClientRegistrationMessage to:com.jme3.network.message.ClientRegistrationMessage$ClientRegistrationSerializer(at)1eaaa323
Registered class[-2]:boolean to:com.jme3.network.serializing.serializers.BooleanSerializer(at)1eaaa81a
Registered class[-3]:byte to:com.jme3.network.serializing.serializers.ByteSerializer(at)1eaaac07
Registered class[-4]:char to:com.jme3.network.serializing.serializers.CharSerializer(at)1eaaafdd
Registered class[-5]:short to:com.jme3.network.serializing.serializers.ShortSerializer(at)1eaab3b3
Registered class[-6]:int to:com.jme3.network.serializing.serializers.IntSerializer(at)1eaab792
Registered class[-7]:long to:com.jme3.network.serializing.serializers.LongSerializer(at)1f041172
Registered class[-8]:float to:com.jme3.network.serializing.serializers.FloatSerializer(at)1f041548
Registered class[-9]:double to:com.jme3.network.serializing.serializers.DoubleSerializer(at)1f041927
Registered class[-10]:class java.lang.Boolean to:com.jme3.network.serializing.serializers.BooleanSerializer(at)1f041d3d
Registered class[-11]:class java.lang.Byte to:com.jme3.network.serializing.serializers.ByteSerializer(at)1f042167
Registered class[-12]:class java.lang.Character to:com.jme3.network.serializing.serializers.CharSerializer(at)1f042552
Registered class[-13]:class java.lang.Short to:com.jme3.network.serializing.serializers.ShortSerializer(at)1f04298f
Registered class[-14]:class java.lang.Integer to:com.jme3.network.serializing.serializers.IntSerializer(at)1f042da2
Registered class[-15]:class java.lang.Long to:com.jme3.network.serializing.serializers.LongSerializer(at)1f0431ba
Registered class[-16]:class java.lang.Float to:com.jme3.network.serializing.serializers.FloatSerializer(at)1f0435a5
Registered class[-17]:class java.lang.Double to:com.jme3.network.serializing.serializers.DoubleSerializer(at)1f043996
Registered class[-18]:class java.lang.String to:com.jme3.network.serializing.serializers.StringSerializer(at)1f043d8c
Registered class[-19]:class com.jme3.math.Vector3f to:com.jme3.network.serializing.serializers.Vector3Serializer(at)1f0441d1
Registered class[-20]:class java.util.Date to:com.jme3.network.serializing.serializers.DateSerializer(at)1f04464f
Registered class[-21]:class java.util.AbstractCollection to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1f044ac0
Registered class[-22]:class java.util.AbstractList to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1f044f5a
Registered class[-23]:class java.util.AbstractSet to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7d126
Registered class[-24]:class java.util.ArrayList to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7d566
Registered class[-25]:class java.util.HashSet to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7d9a3
Registered class[-26]:class java.util.LinkedHashSet to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7dde2
Registered class[-27]:class java.util.LinkedList to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7e267
Registered class[-28]:class java.util.TreeSet to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7e6a4
Registered class[-29]:class java.util.Vector to:com.jme3.network.serializing.serializers.CollectionSerializer(at)1ec7eade
Registered class[-30]:class java.util.AbstractMap to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec7ef1a
Registered class[-31]:class java.util.jar.Attributes to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec7f38a
Registered class[-32]:class java.util.HashMap to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec7f7ac
Registered class[-33]:class java.util.Hashtable to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec7fb96
Registered class[-34]:class java.util.IdentityHashMap to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec7fffb
Registered class[-35]:class java.util.TreeMap to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec8041e
Registered class[-36]:class java.util.WeakHashMap to:com.jme3.network.serializing.serializers.MapSerializer(at)1ec8083c
Registered class[-37]:class java.lang.Enum to:com.jme3.network.serializing.serializers.EnumSerializer(at)1ec80c2a
Registered class[-38]:class com.jme3.network.message.GZIPCompressedMessage to:com.jme3.network.serializing.serializers.GZIPSerializer(at)1ec810d7
Registered class[-39]:class com.jme3.network.message.ZIPCompressedMessage to:com.jme3.network.serializing.serializers.ZIPSerializer(at)1ec81584

It failed here in the simulator because proguard stripped some of the java.net. classes. I added them to the ‘keep’ exceptions and it worked in the simulator and continued on to work ok,
When I try it on an IPAD device it fails here at this same place.
Any ideas?

Registered class[-41]:class com.jme3.network.serializing.serializers.FieldSerializer to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-40]:class com.jme3.network.message.ChannelInfoMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-43]:class MessagesAbstract.ChatMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-45]:class MessagesAbstract.ClientJoinMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-46]:class MessagesAbstract.HandshakeMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-47]:class MessagesAbstract.ServerJoinMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0
Registered class[-48]:class MessagesAbstract.StartGameMessage to:com.jme3.network.serializing.serializers.FieldSerializer(at)1eaa9ab0

Hard to say without log. But if you say it runs in the simulator and fails on your iPad, then it could be a 64 bit problem. Has your iPad a 64 bit CPU? Then change architectures to ARM only. (Of course you cannot submit such an app, because of the ARM64 requirement.)

Are you using the latest iOS plugin? I could get the default project running on my 64 bit iPad exactly once, but now it fails. Still investigating…

Maybe your app uses reflection. See item 5.

it is something to do with serialising network messages. Or more specifically FieldSerializer.

If I remove them it works fine.

I’ve selected a single architecture ARMv7 and its still a problem.

You can reproduce the problem by just registering any network message.

serialiser.registerclass(for any message) and it shows the error.

No other code needed.

Just post example code.

Im just using the standard handshake message from monekyzone and the register class (at bottom).

wont run on IOS device.

@Serializable()
public class HandshakeMessage extends AbstractMessage {

public int protocol_version;

public int client_version;

public int server_version;

public HandshakeMessage() {
}

/**
 *
 * @param protocol_version
 * @param client_version
 * @param server_version
 */
public HandshakeMessage(int protocol_version, int client_version, int server_version) {
    this.protocol_version = protocol_version;
    this.client_version = client_version;
    this.server_version = server_version;
}
private static final Logger LOG = Logger.getLogger(HandshakeMessage.class.getName());

}

    Serializer.registerClass(HandshakeMessage.class);

Which iOS plug-in version are you using? (Old version does not disable JIT which is required for reflections)
Does it run on a 32bit device or 64bit device?
And where does it fail? (32 or 64 bit device)
Without further log, I guess you need to disable JIT (Item 5), because registerClass() uses reflection.

As a note, when disabling the iOS deployment and deleting the ios folder, make sure you also delete the ios folder in “resources” manually, otherwise the new application base for iOS might not be installed (the deployment keeps any files that are different from the ones it installs).

Yes, this was a pain to find out. Added to my experience list. :smiley:

This is my entire code, as you can see its the basic game template with 1 additon for register class. The message that is being registered is above in the thread.

I’m disabling reflection using the ‘threshold’ option as in the current IOS plugin.

Im using XCODE 6.1.1 with SDK 8.1 IOS Plugin 3.0.0.1567 (latest), Im using 1.7JDK

How can I check if I using correct version of Avian?

Also, has anyone tried using JME networking with the new Avian and SDK 8.1 etc??

package mygame;

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.network.serializing.Serializer;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;

/**

  • test

  • @author normenhansen
    */
    public class Main extends SimpleApplication {

    public static void main(String[] args) {
    Main app = new Main();
    app.start();
    }

    @Override
    public void simpleInitApp() {

     Serializer.registerClass(HandshakeMessage.class);
     
     
     
     Box b = new Box(1, 1, 1);
     Geometry geom = new Geometry("Box", b);
    
     Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
     mat.setColor("Color", ColorRGBA.Blue);
     geom.setMaterial(mat);
    
     rootNode.attachChild(geom);
    

    }

    @Override
    public void simpleUpdate(float tpf) {
    //TODO: add update code
    }

    @Override
    public void simpleRender(RenderManager rm) {
    //TODO: add render code
    }
    }

Oh, I think you already provided the relevant information above. Java’s zip implementation uses ISO-8859-1 encoding, but Avian does only support UTF-8. (I think this is against the spec.)

For zip I have a workaround. (Or to be precise for the previous SDK iOS plug-in. I’ll try to get it running with the new version. I’ll add it to my list if I have success.)

But in general it’s not always possible to provide a workaround. For example I could not get Properties.load() running. Maybe it’s time to contact the Avian developer. :grin:

1 Like

thanks for preserving my sanity. However, the question I ask with dread is, “Is there any thing I can do to get it working for now or do I have to put IOS on hold?”

I will contact Avian developer too but how long do you think it would be before you could address it?

Could I, should I roll back to a previous SDK? If so, which works and is it still available?

I’m using 3.0.10 Stable btw.

Added my workaround to the list (item 4) for previous SDK iOS plug-in. Sorry, but I can’t tell you if this fixes your problem. Your registerClass() still fails…

I think you’ll have to add log messages (to the jme3 classes) until you know exactly the line which fails…

Bad news: Looks like that ARM64 does not run. After adding ARM64 to architectures the app crashes. I guess an option is missing somewhere? (I played around with no success)

The default project runs until you click “autofix settings” or add ARM64.

Nah, I tried arm64 myself on my iPhone6, must be something else.

1 Like

Thanks. Good to know. Xcode drives me nuts… :laughing:

Theres been some fixes for JNI calls on avian just yesterday, I committed a build of that, should be in the update center. Make sure you go to the iOS settings page of a project once to install the new avian compiler.

1 Like

Latest iOS plug-in makes the default project run with ARM64! Thanks!!! :smiley:

Unfortunately I have to turn off logging in JmeAppHarness.java, otherwise it crashes in DecimalFormat.applyPattern().
I haven’t changed logging or something, it’s the pure default project. It was only my guess that logging uses DecimalFormat somewhere. And I could be wrong, but turning logging off helped.

ARM64 has some problems. :disappointed:

Reproducible one liner:

assetManager.loadModel("Models/Sinbad/Sinbad.mesh.xml"); // from from jME3-testdata.jar

Crashes in sun.misc.FloatingDecimal.readJavaFormatString()
(Causing line is marked with XXX)

ARM64 crashes if some ogg files are loaded. It doesn’t crash after loading one file,
but the more files are loaded the more likely it is.
The ogg files do not seem to play a role, I just replaced my files with randomly chosen from jME.

public void simpleInitApp() {
    // sounds from jME3-testdata.jar and nifty-examples.jar
    new com.jme3.audio.AudioNode(assetManager, "Beep.ogg", false);
    new com.jme3.audio.AudioNode(assetManager, "intro.ogg", false);
    new com.jme3.audio.AudioNode(assetManager, "Foot steps.ogg", false);
    new com.jme3.audio.AudioNode(assetManager, "a.ogg", false);
    // Still no crash? Add more files... 
} 

The crash happens either in
de.jarnbjo.vorbis.AudioPacket.getPcm()
or in
de.jarnbjo.vorbis.MdctFloat.imdct()

(Causing line is marked with XXX)

Annotations are also not supported on iOS!!! I once met that fact some time ago, but didn’t feel the need to write it down. :sob: (I registered a nifty listener through an annotation, but in this case the error message was quite self explaining.)

Reproducible with:

Main.class.isAnnotationPresent(Serializable.class); // works fine (Main class has no annotations)
HandshakeMessage.class.isAnnotationPresent(Serializable.class); // crashes

com.jme3.network.serializing.Serializer.registerClass() uses isAnnotationPresent() and getAnnotation() etc…
Currently I don’t know a workaround. :frowning: