Long story short, this innocous code accessing .self at the global level causes a NRE in 8.3.1925 & 8.3.1963
public class MyClass
{
}
let c = MyClass.self
print("\(c)")
: error E0: Internal error: JIOE->D201
: error E253: Error while generating executable: Object reference not set to an instance of an object
That of course should not happen. However, what is this code supposed to do ? You probably want MyClass.type, which returns a “Class<MyClass>” on Java.
That’s what MyClass.self does in swift: returns an object representing the type, of type MyClass.Type
This actually works fine (returns a java.lang.Class) if MyClass.self is not called at the global scope
I spent a while battling this NRE and other related issues while prototyping some reflection code, until I realised it worked if I put it in a function.
Incidentally, the related .dynamicType property seems to be broken.
This code gives
class MyClass
{
init() {}
}
func hello()
{
let m = MyClass()
let t = m.dynamicType
}
hello()
/Users/jon/Documents/SilverReflectionTests4/Program.swift(12,10): error E119: Cannot use the unary operator "DynamicType" on type "MyClass"
Thanks.
In working around .dynamicType not working, I found a couple of peculiarities around calling the Java getClass() method.
The generics around Class<?> don’t quite work.
The snippet below is a common pattern in Java to create an object dynamically based on a class, and the return type is the same type as Class.
NB in apple swift the equivalent using .Type syntax works:
func getObjectOfClass( type: T.Type ) -> T?
Fire/Silver can’t quite work it out:
class MyClass
{
}
func getObjectOfClass<T>( clazz: java.lang.Class<T> ) -> T?
{
return nil
}
let obj: MyClass = getObjectOfClass( MyClass.self )
print("\(obj)")
Program.swift(11,20): error E209: Generic parameter "T" for this method call could not fully be resolved
Calling object.getClass() sometimes emits weird bytecode using DynamicHelper
This then usually either fails at runtime with an exception or a Verify error.
The following function is an attempt to mask .dynamicType not working by instead calling out to a util function that will use .dynamicType or .getClass() based on platform:
class Reflection
{
public static func getType(instance: AnyObject) -> java.lang.Class
{
let ret: java.lang.Class = instance.getClass()
return ret
}
}
The decompilation of the emitted function is:
public static Class<Object> getType(Object instance) {
if(instance == null) {
throw new IllegalArgumentException("instance");
} else {
Object ret = (Object)((Object)DynamicHelpers.Invoke(instance, "getClass", 2, new Object[0]));
return (Class)ret;
}
}
This looks like it should work fine (if maybe slow because of unnecessary use of reflection), but you get
03-28 21:35:33.214 3766-3768/? I/dex2oat: java.lang.Class Reflection.getType(java.lang.Object) failed to verify: java.lang.Class Reflection.getType(java.lang.Object): [0x19] returning ‘Reference: java.lang.Object’, but expected from declaration 'Precise Reference: java.lang.Class’
03-28 21:35:38.832 3799-3812/TestRunner: java.lang.VerifyError: Rejecting class Reflection because it failed compile-time verification (declaration of ‘Reflection’ appears in /data/app/test-2/base.apk)