IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
ObjectStreamClass.cs
Go to the documentation of this file.
1/*
2 Copyright (C) 2007-2014 Jeroen Frijters
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely, subject to the following restrictions:
11
12 1. The origin of this software must not be misrepresented; you must not
13 claim that you wrote the original software. If you use this software
14 in a product, an acknowledgment in the product documentation would be
15 appreciated but is not required.
16 2. Altered source versions must be plainly marked as such, and must not be
17 misrepresented as being the original software.
18 3. This notice may not be removed or altered from any source distribution.
19
20 Jeroen Frijters
21 jeroen@frijters.net
22
23*/
24using System;
25using System.Reflection;
26using IKVM.Runtime;
27
28#if !NO_REF_EMIT
29using System.Reflection.Emit;
30
31#endif
32
34{
35
36 static class ObjectStreamClass
37 {
38
39 static class IOHelpers
40 {
41
42 public static void WriteByte(byte[] buf, int offset, byte value)
43 {
44 buf[offset] = value;
45 }
46
47 public static void WriteBoolean(byte[] buf, int offset, bool value)
48 {
49 buf[offset] = value ? (byte)1 : (byte)0;
50 }
51
52 public static void WriteChar(byte[] buf, int offset, char value)
53 {
54 buf[offset + 0] = (byte)(value >> 8);
55 buf[offset + 1] = (byte)(value >> 0);
56 }
57
58 public static void WriteShort(byte[] buf, int offset, short value)
59 {
60 buf[offset + 0] = (byte)(value >> 8);
61 buf[offset + 1] = (byte)(value >> 0);
62 }
63
64 public static void WriteInt(byte[] buf, int offset, int value)
65 {
66 buf[offset + 0] = (byte)(value >> 24);
67 buf[offset + 1] = (byte)(value >> 16);
68 buf[offset + 2] = (byte)(value >> 8);
69 buf[offset + 3] = (byte)(value >> 0);
70 }
71
72 public static void WriteFloat(byte[] buf, int offset, float value)
73 {
74#if !FIRST_PASS && !IMPORTER
75 global::java.io.Bits.putFloat(buf, offset, value);
76#endif
77 }
78
79 public static void WriteLong(byte[] buf, int offset, long value)
80 {
81 WriteInt(buf, offset, (int)(value >> 32));
82 WriteInt(buf, offset + 4, (int)value);
83 }
84
85 public static void WriteDouble(byte[] buf, int offset, double value)
86 {
87#if !FIRST_PASS && !IMPORTER
88 global::java.io.Bits.putDouble(buf, offset, value);
89#endif
90 }
91
92 public static byte ReadByte(byte[] buf, int offset)
93 {
94 return buf[offset];
95 }
96
97 public static bool ReadBoolean(byte[] buf, int offset)
98 {
99 return buf[offset] != 0;
100 }
101
102 public static char ReadChar(byte[] buf, int offset)
103 {
104 return (char)((buf[offset] << 8) + buf[offset + 1]);
105 }
106
107 public static short ReadShort(byte[] buf, int offset)
108 {
109 return (short)((buf[offset] << 8) + buf[offset + 1]);
110 }
111
112 public static int ReadInt(byte[] buf, int offset)
113 {
114 return (buf[offset + 0] << 24)
115 + (buf[offset + 1] << 16)
116 + (buf[offset + 2] << 8)
117 + (buf[offset + 3] << 0);
118 }
119
120 public static float ReadFloat(byte[] buf, int offset)
121 {
122#if FIRST_PASS || IMPORTER
123 return 0;
124#else
125 return global::java.lang.Float.intBitsToFloat(ReadInt(buf, offset));
126#endif
127 }
128
129 public static long ReadLong(byte[] buf, int offset)
130 {
131 long hi = (uint)ReadInt(buf, offset);
132 long lo = (uint)ReadInt(buf, offset + 4);
133 return lo + (hi << 32);
134 }
135
136 public static double ReadDouble(byte[] buf, int offset)
137 {
138#if FIRST_PASS || IMPORTER
139 return 0;
140#else
141 return global::java.lang.Double.longBitsToDouble(ReadLong(buf, offset));
142#endif
143 }
144 }
145
146 public static void initNative()
147 {
148 }
149
150 public static bool isDynamicTypeWrapper(global::java.lang.Class cl)
151 {
152 RuntimeJavaType wrapper = RuntimeJavaType.FromClass(cl);
153 return !wrapper.IsFastClassLiteralSafe;
154 }
155
156 public static bool hasStaticInitializer(global::java.lang.Class cl)
157 {
158 var wrapper = RuntimeJavaType.FromClass(cl);
159 try
160 {
161 wrapper.Finish();
162 }
164 {
165 throw x.ToJava();
166 }
167
168 var type = wrapper.TypeAsTBD;
169 if (!type.IsArray && type.TypeInitializer != null)
170 {
171 wrapper.RunClassInit();
172 return !wrapper.Context.AttributeHelper.IsHideFromJava(type.TypeInitializer);
173 }
174
175 return false;
176 }
177
178#if !FIRST_PASS && !NO_REF_EMIT
179
180 private sealed class FastFieldReflector : global::ikvm.@internal.FieldReflectorBase
181 {
182
183 private static readonly MethodInfo ReadByteMethod = typeof(IOHelpers).GetMethod("ReadByte");
184 private static readonly MethodInfo ReadBooleanMethod = typeof(IOHelpers).GetMethod("ReadBoolean");
185 private static readonly MethodInfo ReadCharMethod = typeof(IOHelpers).GetMethod("ReadChar");
186 private static readonly MethodInfo ReadShortMethod = typeof(IOHelpers).GetMethod("ReadShort");
187 private static readonly MethodInfo ReadIntMethod = typeof(IOHelpers).GetMethod("ReadInt");
188 private static readonly MethodInfo ReadFloatMethod = typeof(IOHelpers).GetMethod("ReadFloat");
189 private static readonly MethodInfo ReadLongMethod = typeof(IOHelpers).GetMethod("ReadLong");
190 private static readonly MethodInfo ReadDoubleMethod = typeof(IOHelpers).GetMethod("ReadDouble");
191 private static readonly MethodInfo WriteByteMethod = typeof(IOHelpers).GetMethod("WriteByte");
192 private static readonly MethodInfo WriteBooleanMethod = typeof(IOHelpers).GetMethod("WriteBoolean");
193 private static readonly MethodInfo WriteCharMethod = typeof(IOHelpers).GetMethod("WriteChar");
194 private static readonly MethodInfo WriteShortMethod = typeof(IOHelpers).GetMethod("WriteShort");
195 private static readonly MethodInfo WriteIntMethod = typeof(IOHelpers).GetMethod("WriteInt");
196 private static readonly MethodInfo WriteFloatMethod = typeof(IOHelpers).GetMethod("WriteFloat");
197 private static readonly MethodInfo WriteLongMethod = typeof(IOHelpers).GetMethod("WriteLong");
198 private static readonly MethodInfo WriteDoubleMethod = typeof(IOHelpers).GetMethod("WriteDouble");
199 private delegate void ObjFieldGetterSetter(object obj, object[] objarr);
200 private delegate void PrimFieldGetterSetter(object obj, byte[] objarr);
201 private static readonly ObjFieldGetterSetter objDummy = new ObjFieldGetterSetter(Dummy);
202 private static readonly PrimFieldGetterSetter primDummy = new PrimFieldGetterSetter(Dummy);
203 private global::java.io.ObjectStreamField[] fields;
204 private ObjFieldGetterSetter objFieldGetter;
205 private PrimFieldGetterSetter primFieldGetter;
206 private ObjFieldGetterSetter objFieldSetter;
207 private PrimFieldGetterSetter primFieldSetter;
208
209 private static void Dummy(object obj, object[] objarr)
210 {
211 }
212
213 private static void Dummy(object obj, byte[] barr)
214 {
215 }
216
217 internal FastFieldReflector(global::java.io.ObjectStreamField[] fields)
218 {
219 this.fields = fields;
220 RuntimeJavaType tw = null;
221 foreach (global::java.io.ObjectStreamField field in fields)
222 {
223 RuntimeJavaField fw = GetFieldWrapper(field);
224 if (fw != null)
225 {
226 if (tw == null)
227 {
228 tw = fw.DeclaringType;
229 }
230 else if (tw != fw.DeclaringType)
231 {
232 // pre-condition is that all fields are from the same Type!
233 throw new global::java.lang.InternalError();
234 }
235 }
236 }
237 if (tw == null)
238 {
239 objFieldGetter = objFieldSetter = objDummy;
240 primFieldGetter = primFieldSetter = primDummy;
241 }
242 else
243 {
244 try
245 {
246 tw.Finish();
247 }
249 {
250 throw x.ToJava();
251 }
252
253 var dmObjGetter = DynamicMethodUtil.Create("__<ObjFieldGetter>", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) });
254 var dmPrimGetter = DynamicMethodUtil.Create("__<PrimFieldGetter>", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) });
255 var dmObjSetter = DynamicMethodUtil.Create("__<ObjFieldSetter>", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(object[]) });
256 var dmPrimSetter = DynamicMethodUtil.Create("__<PrimFieldSetter>", tw.TypeAsBaseType, true, null, new Type[] { typeof(object), typeof(byte[]) });
257 var ilgenObjGetter = JVM.Context.CodeEmitterFactory.Create(dmObjGetter);
258 var ilgenPrimGetter = JVM.Context.CodeEmitterFactory.Create(dmPrimGetter);
259 var ilgenObjSetter = JVM.Context.CodeEmitterFactory.Create(dmObjSetter);
260 var ilgenPrimSetter = JVM.Context.CodeEmitterFactory.Create(dmPrimSetter);
261
262 // we want the getters to be verifiable (because writeObject can be used from partial trust),
263 // so we create a local to hold the properly typed object reference
264 var objGetterThis = ilgenObjGetter.DeclareLocal(tw.TypeAsBaseType);
265 var primGetterThis = ilgenPrimGetter.DeclareLocal(tw.TypeAsBaseType);
266 ilgenObjGetter.Emit(OpCodes.Ldarg_0);
267 ilgenObjGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
268 ilgenObjGetter.Emit(OpCodes.Stloc, objGetterThis);
269 ilgenPrimGetter.Emit(OpCodes.Ldarg_0);
270 ilgenPrimGetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
271 ilgenPrimGetter.Emit(OpCodes.Stloc, primGetterThis);
272
273 foreach (global::java.io.ObjectStreamField field in fields)
274 {
275 RuntimeJavaField fw = GetFieldWrapper(field);
276 if (fw == null)
277 {
278 continue;
279 }
280 fw.ResolveField();
281 RuntimeJavaType fieldType = fw.FieldTypeWrapper;
282 try
283 {
284 fieldType = fieldType.EnsureLoadable(tw.ClassLoader);
285 fieldType.Finish();
286 }
288 {
289 throw x.ToJava();
290 }
291 if (fieldType.IsPrimitive)
292 {
293 // Getter
294 ilgenPrimGetter.Emit(OpCodes.Ldarg_1);
295 ilgenPrimGetter.EmitLdc_I4(field.getOffset());
296 ilgenPrimGetter.Emit(OpCodes.Ldloc, primGetterThis);
297 fw.EmitGet(ilgenPrimGetter);
298 if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.BYTE)
299 {
300 ilgenPrimGetter.Emit(OpCodes.Call, WriteByteMethod);
301 }
302 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.BOOLEAN)
303 {
304 ilgenPrimGetter.Emit(OpCodes.Call, WriteBooleanMethod);
305 }
306 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.CHAR)
307 {
308 ilgenPrimGetter.Emit(OpCodes.Call, WriteCharMethod);
309 }
310 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.SHORT)
311 {
312 ilgenPrimGetter.Emit(OpCodes.Call, WriteShortMethod);
313 }
314 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.INT)
315 {
316 ilgenPrimGetter.Emit(OpCodes.Call, WriteIntMethod);
317 }
318 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.FLOAT)
319 {
320 ilgenPrimGetter.Emit(OpCodes.Call, WriteFloatMethod);
321 }
322 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.LONG)
323 {
324 ilgenPrimGetter.Emit(OpCodes.Call, WriteLongMethod);
325 }
326 else if (fieldType == ilgenPrimGetter.Context.PrimitiveJavaTypeFactory.DOUBLE)
327 {
328 ilgenPrimGetter.Emit(OpCodes.Call, WriteDoubleMethod);
329 }
330 else
331 {
332 throw new global::java.lang.InternalError();
333 }
334
335 // Setter
336 ilgenPrimSetter.Emit(OpCodes.Ldarg_0);
337 ilgenPrimSetter.Emit(OpCodes.Castclass, tw.TypeAsBaseType);
338 ilgenPrimSetter.Emit(OpCodes.Ldarg_1);
339 ilgenPrimSetter.EmitLdc_I4(field.getOffset());
340 if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.BYTE)
341 {
342 ilgenPrimSetter.Emit(OpCodes.Call, ReadByteMethod);
343 }
344 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.BOOLEAN)
345 {
346 ilgenPrimSetter.Emit(OpCodes.Call, ReadBooleanMethod);
347 }
348 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.CHAR)
349 {
350 ilgenPrimSetter.Emit(OpCodes.Call, ReadCharMethod);
351 }
352 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.SHORT)
353 {
354 ilgenPrimSetter.Emit(OpCodes.Call, ReadShortMethod);
355 }
356 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.INT)
357 {
358 ilgenPrimSetter.Emit(OpCodes.Call, ReadIntMethod);
359 }
360 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.FLOAT)
361 {
362 ilgenPrimSetter.Emit(OpCodes.Call, ReadFloatMethod);
363 }
364 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.LONG)
365 {
366 ilgenPrimSetter.Emit(OpCodes.Call, ReadLongMethod);
367 }
368 else if (fieldType == ilgenPrimSetter.Context.PrimitiveJavaTypeFactory.DOUBLE)
369 {
370 ilgenPrimSetter.Emit(OpCodes.Call, ReadDoubleMethod);
371 }
372 else
373 {
374 throw new global::java.lang.InternalError();
375 }
376 fw.EmitSet(ilgenPrimSetter);
377 }
378 else
379 {
380 // Getter
381 ilgenObjGetter.Emit(OpCodes.Ldarg_1);
382 ilgenObjGetter.EmitLdc_I4(field.getOffset());
383 ilgenObjGetter.Emit(OpCodes.Ldloc, objGetterThis);
384 fw.EmitGet(ilgenObjGetter);
385 fieldType.EmitConvSignatureTypeToStackType(ilgenObjGetter);
386 ilgenObjGetter.Emit(OpCodes.Stelem_Ref);
387
388 // Setter
389 ilgenObjSetter.Emit(OpCodes.Ldarg_0);
390 ilgenObjSetter.Emit(OpCodes.Ldarg_1);
391 ilgenObjSetter.EmitLdc_I4(field.getOffset());
392 ilgenObjSetter.Emit(OpCodes.Ldelem_Ref);
393 fieldType.EmitCheckcast(ilgenObjSetter);
394 fieldType.EmitConvStackTypeToSignatureType(ilgenObjSetter, null);
395 fw.EmitSet(ilgenObjSetter);
396 }
397 }
398 ilgenObjGetter.Emit(OpCodes.Ret);
399 ilgenPrimGetter.Emit(OpCodes.Ret);
400 ilgenObjSetter.Emit(OpCodes.Ret);
401 ilgenPrimSetter.Emit(OpCodes.Ret);
402 ilgenObjGetter.DoEmit();
403 ilgenPrimGetter.DoEmit();
404 ilgenObjSetter.DoEmit();
405 ilgenPrimSetter.DoEmit();
406 objFieldGetter = (ObjFieldGetterSetter)dmObjGetter.CreateDelegate(typeof(ObjFieldGetterSetter));
407 primFieldGetter = (PrimFieldGetterSetter)dmPrimGetter.CreateDelegate(typeof(PrimFieldGetterSetter));
408 objFieldSetter = (ObjFieldGetterSetter)dmObjSetter.CreateDelegate(typeof(ObjFieldGetterSetter));
409 primFieldSetter = (PrimFieldGetterSetter)dmPrimSetter.CreateDelegate(typeof(PrimFieldGetterSetter));
410 }
411 }
412
413 private static RuntimeJavaField GetFieldWrapper(global::java.io.ObjectStreamField field)
414 {
415 global::java.lang.reflect.Field f = field.getField();
416 return f == null ? null : RuntimeJavaField.FromField(f);
417 }
418
419 public override global::java.io.ObjectStreamField[] getFields()
420 {
421 return fields;
422 }
423
424 public override void getObjFieldValues(object obj, object[] objarr)
425 {
426 objFieldGetter(obj, objarr);
427 }
428
429 public override void setObjFieldValues(object obj, object[] objarr)
430 {
431 objFieldSetter(obj, objarr);
432 }
433
434 public override void getPrimFieldValues(object obj, byte[] barr)
435 {
436 primFieldGetter(obj, barr);
437 }
438
439 public override void setPrimFieldValues(object obj, byte[] barr)
440 {
441 primFieldSetter(obj, barr);
442 }
443 }
444#endif // !FIRST_PASS && !NO_REF_EMIT
445
446 public static object getFastFieldReflector(global::java.io.ObjectStreamField[] fieldsObj)
447 {
448#if FIRST_PASS || NO_REF_EMIT
449 return null;
450#else
451 return new FastFieldReflector(fieldsObj);
452#endif
453 }
454 }
455
456}
IKVM.Reflection.Type Type
IKVM.Reflection.MethodInfo MethodInfo
static bool isDynamicTypeWrapper(global::java.lang.Class cl)
static object getFastFieldReflector(global::java.io.ObjectStreamField[] fieldsObj)
static bool hasStaticInitializer(global::java.lang.Class cl)
CodeEmitter Create(MethodBuilder mb)
Creates a new instance.
Provides utilities for working with dynamic methods.
Main state of the running JVM.
.NET exception that corresponds to a Java exception.
CodeEmitterFactory CodeEmitterFactory
Gets the CodeEmitterFactory associated with this instance of the runtime.