47 CustomAttributeBuilder serializableAttribute;
48 CustomAttributeBuilder securityCriticalAttribute;
49 RuntimeJavaType typeOfISerializable;
50 RuntimeJavaType typeofIObjectreference;
51 RuntimeJavaType typeOfExternalizable;
59 this.context = context ??
throw new ArgumentNullException(nameof(context));
62 CustomAttributeBuilder SerializableAttribute => serializableAttribute ??=
new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SerializableAttribute).FullName).GetConstructor([]).AsReflection(), Array.Empty<
object>());
64 CustomAttributeBuilder SecurityCriticalAttribute => securityCriticalAttribute ??=
new CustomAttributeBuilder(context.Resolver.ResolveCoreType(typeof(SecurityCriticalAttribute).FullName).GetConstructor([]).AsReflection(), Array.Empty<
object>());
66 RuntimeJavaType TypeOfISerializable => typeOfISerializable ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).AsReflection());
68 RuntimeJavaType TypeOfIObjectReference => typeofIObjectreference ??= context.ClassLoaderFactory.GetJavaTypeFromType(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection());
70 RuntimeJavaType TypeOfExternalizable => typeOfExternalizable ??= context.ClassLoaderFactory.LoadClassCritical(
"java.io.Externalizable");
72 internal bool IsISerializable(RuntimeJavaType wrapper)
74 return wrapper == TypeOfISerializable;
77 bool IsSafeForAutomagicSerialization(RuntimeJavaType wrapper)
79 if (wrapper.TypeAsBaseType.IsSerializable)
81 else if (wrapper.IsSubTypeOf(TypeOfISerializable))
83 else if (wrapper.IsSubTypeOf(TypeOfIObjectReference))
85 else if (wrapper.GetMethod(
"GetObjectData",
"(Lcli.System.Runtime.Serialization.SerializationInfo;Lcli.System.Runtime.Serialization.StreamingContext;)V",
false) !=
null)
87 else if (wrapper.GetMethod(
"<init>",
"(Lcli.System.Runtime.Serialization.SerializationInfo;Lcli.System.Runtime.Serialization.StreamingContext;)V",
false) !=
null)
93 internal MethodBuilder AddAutomagicSerialization(RuntimeByteCodeJavaType wrapper, TypeBuilder typeBuilder)
95 MethodBuilder serializationCtor =
null;
98 MarkSerializable(typeBuilder);
100 else if (wrapper.IsSubTypeOf(wrapper.Context.JavaBase.TypeOfJavaIoSerializable) && IsSafeForAutomagicSerialization(wrapper))
102 if (wrapper.IsSubTypeOf(TypeOfExternalizable))
104 var ctor = wrapper.GetMethod(
"<init>",
"()V",
false);
105 if (ctor !=
null && ctor.IsPublic)
107 MarkSerializable(typeBuilder);
110 serializationCtor = AddConstructor(typeBuilder, ctor,
null,
true);
111 if (!wrapper.BaseTypeWrapper.IsSubTypeOf(wrapper.Context.JavaBase.TypeOfJavaIoSerializable))
113 AddGetObjectData(typeBuilder);
115 if (wrapper.BaseTypeWrapper.GetMethod(
"readResolve",
"()Ljava.lang.Object;",
true) !=
null)
117 RemoveReadResolve(typeBuilder);
121 else if (wrapper.BaseTypeWrapper.IsSubTypeOf(wrapper.Context.JavaBase.TypeOfJavaIoSerializable))
123 var baseCtor = wrapper.GetBaseSerializationConstructor();
124 if (baseCtor !=
null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly))
126 MarkSerializable(typeBuilder);
127 serializationCtor = AddConstructor(typeBuilder,
null, baseCtor,
false);
128 AddReadResolve(wrapper, typeBuilder);
133 var baseCtor = wrapper.BaseTypeWrapper.GetMethod(
"<init>",
"()V",
false);
134 if (baseCtor !=
null && baseCtor.IsAccessibleFrom(wrapper.BaseTypeWrapper, wrapper, wrapper))
136 MarkSerializable(typeBuilder);
137 AddGetObjectData(typeBuilder);
143 serializationCtor = AddConstructor(typeBuilder, baseCtor,
null,
true);
144 AddReadResolve(wrapper, typeBuilder);
149 return serializationCtor;
152 internal MethodBuilder AddAutomagicSerializationToWorkaroundBaseClass(TypeBuilder typeBuilderWorkaroundBaseClass,
MethodBase baseCtor)
154 if (typeBuilderWorkaroundBaseClass.BaseType.IsSerializable)
156 typeBuilderWorkaroundBaseClass.SetCustomAttribute(SerializableAttribute);
157 if (baseCtor !=
null && (baseCtor.IsFamily || baseCtor.IsFamilyOrAssembly))
158 return AddConstructor(typeBuilderWorkaroundBaseClass,
null, baseCtor,
false);
164 internal void MarkSerializable(TypeBuilder tb)
166 tb.SetCustomAttribute(SerializableAttribute);
169 internal void AddGetObjectData(TypeBuilder tb)
171 var name = tb.IsSealed ?
"System.Runtime.Serialization.ISerializable.GetObjectData" :
"GetObjectData";
172 var attr = tb.IsSealed
173 ? MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final
174 : MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.CheckAccessOnOverride;
175 tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).AsReflection());
176 var getObjectData = tb.DefineMethod(name, attr,
null,
new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() });
177 getObjectData.SetCustomAttribute(SecurityCriticalAttribute);
178 context.AttributeHelper.HideFromJava(getObjectData);
179 tb.DefineMethodOverride(getObjectData, context.Resolver.ResolveCoreType(typeof(ISerializable).FullName).GetMethod(
"GetObjectData").AsReflection());
180 CodeEmitter ilgen = context.CodeEmitterFactory.Create(getObjectData);
181 ilgen.Emit(OpCodes.Ldarg_0);
182 ilgen.Emit(OpCodes.Ldarg_1);
183 RuntimeJavaType serializationHelper = context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.Serialization");
184 RuntimeJavaMethod mw = serializationHelper.GetMethod(
"writeObject",
"(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V",
false);
187 ilgen.Emit(OpCodes.Ret);
191 MethodBuilder AddConstructor(TypeBuilder tb, RuntimeJavaMethod defaultConstructor,
MethodBase serializationConstructor,
bool callReadObject)
193 MethodBuilder ctor = ReflectUtil.DefineConstructor(tb, MethodAttributes.Family,
new Type[] { context.Resolver.ResolveCoreType(typeof(SerializationInfo).FullName).AsReflection(), context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() });
194 context.AttributeHelper.HideFromJava(ctor);
195 CodeEmitter ilgen = context.CodeEmitterFactory.Create(ctor);
196 ilgen.Emit(OpCodes.Ldarg_0);
197 if (defaultConstructor !=
null)
199 defaultConstructor.EmitCall(ilgen);
203 ilgen.Emit(OpCodes.Ldarg_1);
204 ilgen.Emit(OpCodes.Ldarg_2);
205 ilgen.Emit(OpCodes.Call, serializationConstructor);
209 ilgen.Emit(OpCodes.Ldarg_0);
210 ilgen.Emit(OpCodes.Ldarg_1);
211 RuntimeJavaType serializationHelper = context.ClassLoaderFactory.LoadClassCritical(
"ikvm.internal.Serialization");
212 RuntimeJavaMethod mw = serializationHelper.GetMethod(
"readObject",
"(Ljava.lang.Object;Lcli.System.Runtime.Serialization.SerializationInfo;)V",
false);
216 ilgen.Emit(OpCodes.Ret);
221 void AddReadResolve(RuntimeByteCodeJavaType wrapper, TypeBuilder tb)
223 var mw = wrapper.GetMethod(
"readResolve",
"()Ljava.lang.Object;",
false);
224 if (mw !=
null && !wrapper.IsSubTypeOf(TypeOfIObjectReference))
226 tb.AddInterfaceImplementation(wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection());
227 var getRealObject = tb.DefineMethod(
"IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, wrapper.Context.Types.Object,
new Type[] { wrapper.Context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection() });
228 getRealObject.SetCustomAttribute(SecurityCriticalAttribute);
229 wrapper.Context.AttributeHelper.HideFromJava(getRealObject);
230 tb.DefineMethodOverride(getRealObject, wrapper.Context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod(
"GetRealObject").AsReflection());
231 var ilgen = context.CodeEmitterFactory.Create(getRealObject);
233 if (!wrapper.IsFinal)
236 ilgen.Emit(OpCodes.Ldarg_0);
237 ilgen.Emit(OpCodes.Callvirt, wrapper.Context.CompilerFactory.GetTypeMethod);
238 ilgen.Emit(OpCodes.Ldtoken, wrapper.TypeAsBaseType);
239 ilgen.Emit(OpCodes.Call, wrapper.Context.CompilerFactory.GetTypeFromHandleMethod);
240 CodeEmitterLabel label = ilgen.DefineLabel();
241 ilgen.EmitBeq(label);
242 ilgen.Emit(OpCodes.Ldarg_0);
243 ilgen.Emit(OpCodes.Ret);
244 ilgen.MarkLabel(label);
246 ilgen.Emit(OpCodes.Ldarg_0);
248 ilgen.Emit(OpCodes.Ret);
253 void RemoveReadResolve(TypeBuilder tb)
255 tb.AddInterfaceImplementation(context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).AsReflection());
256 MethodBuilder getRealObject = tb.DefineMethod(
"IObjectReference.GetRealObject", MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final, context.Types.Object, [context.Resolver.ResolveCoreType(typeof(StreamingContext).FullName).AsReflection()]);
257 getRealObject.SetCustomAttribute(SecurityCriticalAttribute);
258 context.AttributeHelper.HideFromJava(getRealObject);
259 tb.DefineMethodOverride(getRealObject, context.Resolver.ResolveCoreType(typeof(IObjectReference).FullName).GetMethod(
"GetRealObject").AsReflection());
260 CodeEmitter ilgen = context.CodeEmitterFactory.Create(getRealObject);
261 ilgen.Emit(OpCodes.Ldarg_0);
262 ilgen.Emit(OpCodes.Ret);