49 static readonly Key EXCEPTION_DATA_KEY =
new Key();
50 static readonly Exception NOT_REMAPPED =
new Exception();
51 static readonly Exception[] EMPTY_THROWABLE_ARRAY =
new Exception[0];
52 static readonly
bool cleanStackTrace =
JVM.SafeGetEnvironmentVariable(
"IKVM_DISABLE_STACKTRACE_CLEANING") ==
null;
55 readonly Dictionary<string, string> failedTypes =
new Dictionary<string, string>();
57#if FIRST_PASS == false
58 readonly ConditionalWeakTable<Exception, Exception> exceptions =
new();
67 this.context = context ??
throw new ArgumentNullException(nameof(context));
69#if FIRST_PASS == false
71 GC.SuppressFinalize(exceptions);
78 internal sealed class ExceptionInfoHelper
96 this.exceptionHelper = exceptionHelper;
97 this.stackTrace = stackTrace;
108 this.exceptionHelper = exceptionHelper;
109 this.tracePart1 = tracePart1;
110 this.tracePart2 = tracePart2;
120 internal ExceptionInfoHelper(
ExceptionHelper exceptionHelper, Exception x,
bool captureAdditionalStackTrace)
122 this.exceptionHelper = exceptionHelper;
124 if (captureAdditionalStackTrace)
129 void OnSerializing(StreamingContext context)
132 get_StackTrace(
null);
137 return (mb.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
144 if (stackTrace ==
null)
146 var list =
new List<StackTraceElement>();
148 if (tracePart1 !=
null)
151 if (cleanStackTrace && t is
java.
lang.NullPointerException && tracePart1.FrameCount > 0)
156 if (tracePart1.GetFrame(0).GetMethod().Name.StartsWith(
"instancehelper_") &&
157 !GetMethodName(tracePart1.GetFrame(0).GetMethod()).StartsWith(
"instancehelper_"))
163 Append(exceptionHelper, list, tracePart1, skip1,
false);
166 if (tracePart2 !=
null && tracePart2.FrameCount > 0)
173 if (tracePart1 ==
null)
175 var mb = tracePart2.GetFrame(skip).GetMethod();
176 if (mb.DeclaringType == typeof(
Throwable) && mb.Name.EndsWith(
"fillInStackTrace", StringComparison.Ordinal))
180 while (tracePart2.FrameCount > skip)
182 mb = tracePart2.GetFrame(skip).GetMethod();
183 if (mb.DeclaringType != typeof(
Throwable) || !mb.Name.EndsWith(
"fillInStackTrace", StringComparison.Ordinal))
189 while (tracePart2.FrameCount > skip)
191 mb = tracePart2.GetFrame(skip).GetMethod();
192 if (mb.Name !=
".ctor" || !mb.DeclaringType.IsInstanceOfType(t))
203 while (tracePart2.FrameCount > skip && IsHideFromJava(tracePart2.GetFrame(skip).GetMethod()))
206 if (tracePart1.FrameCount > 0 &&
207 tracePart2.FrameCount > skip &&
208 tracePart1.GetFrame(tracePart1.FrameCount - 1).GetMethod() == tracePart2.GetFrame(skip).GetMethod())
216 Append(exceptionHelper, list, tracePart2, skip,
true);
219 if (cleanStackTrace && list.Count > 0)
221 var elem = list[list.Count - 1];
222 if (elem.getClassName() ==
"java.lang.reflect.Method")
223 list.RemoveAt(list.Count - 1);
228 this.stackTrace = list.ToArray();
235 internal static void Append(
ExceptionHelper exceptionHelper, List<StackTraceElement> stackTrace,
StackTrace st,
int skip,
bool isLast)
237 for (
int i = skip; i < st.FrameCount; i++)
239 var frame = st.GetFrame(i);
240 var m = frame.GetMethod();
244 var type = m.DeclaringType;
245 if (cleanStackTrace &&
248 || type == typeof(RuntimeMethodHandle)
249 || (type == typeof(
Throwable) && m.Name ==
"instancehelper_fillInStackTrace")
250 || (m.Name ==
"ToJava" && typeof(RetargetableJavaException).IsAssignableFrom(type))
252 || IsPrivateScope(m)))
257 var lineNumber = frame.GetFileLineNumber();
259 lineNumber = exceptionHelper.GetLineNumber(frame);
261 var fileName = frame.GetFileName();
262 if (fileName !=
null)
266 fileName =
new System.IO.FileInfo(fileName).Name;
276 fileName ??= exceptionHelper.GetFileName(frame);
277 stackTrace.Add(
new StackTraceElement(exceptionHelper.GetClassNameFromType(type), GetMethodName(m), fileName, IsNative(m) ? -2 : lineNumber));
280 if (cleanStackTrace && isLast)
281 while (stackTrace.Count > 0 && stackTrace[stackTrace.Count - 1].getClassName().StartsWith(
"cli.System.Threading.", StringComparison.Ordinal))
282 stackTrace.RemoveAt(stackTrace.Count - 1);
289 sealed class Key : ISerializable
293 sealed class Helper : IObjectReference
297 public object GetRealObject(StreamingContext context)
299 return EXCEPTION_DATA_KEY;
305 public void GetObjectData(SerializationInfo info, StreamingContext context)
307 info.SetType(typeof(Helper));
315 if (methodFlagAttribs.Length == 1)
318 return (modifiersAttrib.Modifiers &
Modifiers.Native) != 0;
327 if (attr.Length == 1)
331 else if (mb.Name ==
".ctor")
335 else if (mb.Name ==
".cctor")
339 else if (mb.Name.StartsWith(NamePrefix.DefaultMethod, StringComparison.Ordinal))
341 return mb.Name.Substring(NamePrefix.DefaultMethod.Length);
343 else if (mb.Name.StartsWith(NamePrefix.Bridge, StringComparison.Ordinal))
345 return mb.Name.Substring(NamePrefix.Bridge.Length);
347 else if (mb.IsSpecialName)
349 return UnicodeUtil.UnescapeInvalidSurrogates(mb.Name);
360 throw new NotImplementedException();
366 string GetClassNameFromType(
Type type)
369 throw new NotImplementedException();
374 if (context.ClassLoaderFactory.IsRemappedType(type))
375 return RuntimeManagedJavaType.GetName(context, type);
377 var tw = context.ClassLoaderFactory.GetJavaTypeFromType(type);
381 return RuntimeManagedJavaType.GetName(context, type);
382 if (tw.IsUnsafeAnonymous)
383 return tw.ClassObject.getName();
388 return type.FullName;
392 int GetLineNumber(StackFrame frame)
394 var ilOffset = frame.GetILOffset();
395 if (ilOffset != StackFrame.OFFSET_UNKNOWN)
397 var mb = frame.GetMethod();
398 if (mb !=
null && mb.DeclaringType !=
null)
400 if (context.ClassLoaderFactory.IsRemappedType(mb.DeclaringType))
403 var tw = context.ClassLoaderFactory.GetJavaTypeFromType(mb.DeclaringType);
405 return tw.GetSourceLineNumber(mb, ilOffset);
412 string GetFileName(StackFrame frame)
414 var mb = frame.GetMethod();
415 if (mb !=
null && mb.DeclaringType !=
null)
417 if (context.ClassLoaderFactory.IsRemappedType(mb.DeclaringType))
420 var tw = context.ClassLoaderFactory.GetJavaTypeFromType(mb.DeclaringType);
422 return tw.GetSourceFileName();
435 internal static object[] GetPersistentFields()
438 throw new NotImplementedException();
444 new ObjectStreamField(
"stackTrace", typeof(global::java.lang.StackTraceElement[])),
458 internal static void WriteObject(Exception e,
object stream)
461 throw new NotImplementedException();
468 fields.put(
"detailMessage", e.Message);
469 fields.put(
"cause", e.InnerException);
471 fields.put(
"suppressedExceptions",
null);
472 fields.put(
"stackTrace", GetOurStackTrace(e));
476 fields.put(
"detailMessage", t.detailMessage);
477 fields.put(
"cause", t.cause);
478 fields.put(
"suppressedExceptions", t.suppressedExceptions);
480 fields.put(
"stackTrace", t.stackTrace ??
java.
lang.ThrowableHelper.SentinelHolder.STACK_TRACE_SENTINEL);
488 internal static void ReadObject(Exception e,
object stream)
491 throw new NotImplementedException();
501 var detailMessage = fields.get(
"detailMessage",
null);
502 var cause = fields.get(
"cause",
null);
503 var ctor = typeof(
Throwable).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[] { typeof(string), typeof(Exception), typeof(bool), typeof(bool) },
null);
506 ctor.Invoke(_this, [detailMessage,
null,
false,
false]);
511 ctor.Invoke(_this, [detailMessage, cause,
false,
false]);
515 _this.suppressedExceptions = (
java.
util.List)fields.get(
"suppressedExceptions",
null);
518 if (_this.suppressedExceptions !=
null)
520 java.util.List suppressed =
null;
521 if (_this.suppressedExceptions.isEmpty())
523 suppressed =
Throwable.SUPPRESSED_SENTINEL;
527 suppressed =
new java.
util.ArrayList(1);
528 for (
int i = 0; i < _this.suppressedExceptions.size(); i++)
530 var entry = (Exception)_this.suppressedExceptions.get(i);
532 throw new java.
lang.NullPointerException(
"Cannot suppress a null exception.");
534 throw new java.
lang.IllegalArgumentException(
"Self-suppression not permitted");
536 suppressed.add(entry);
540 _this.suppressedExceptions = suppressed;
543 if (_this.stackTrace !=
null)
545 if (_this.stackTrace.Length == 0)
547 _this.stackTrace = [];
549 else if (_this.stackTrace.Length == 1 &&
java.
lang.ThrowableHelper.SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(_this.stackTrace[0]))
551 _this.stackTrace =
null;
555 foreach (var elem
in _this.stackTrace)
557 throw new java.
lang.NullPointerException(
"null StackTraceElement in serial stream. ");
562 _this.stackTrace = [];
568 internal static string FilterMessage(
string message)
570 return message ??
"";
573 internal static string GetMessageFromCause(Exception cause)
576 throw new NotImplementedException();
578 return cause !=
null ? ikvm.extensions.ExtensionMethods.toString(cause) :
"";
582 internal static string GetLocalizedMessage(Exception x)
585 throw new NotImplementedException();
587 return ikvm.extensions.ExtensionMethods.getMessage(x);
591 internal static string ToString(Exception x)
594 throw new NotImplementedException();
596 var message = ikvm.extensions.ExtensionMethods.getLocalizedMessage(x);
598 return ikvm.extensions.ExtensionMethods.getClass(x).getName();
600 return ikvm.extensions.ExtensionMethods.getClass(x).getName() +
": " + message;
604 internal static Exception GetCause(Exception _this)
607 throw new NotImplementedException();
612 return cause == _this ? null : cause;
617 internal static void CheckInitCause(Exception
self, Exception self_cause, Exception cause)
620 throw new NotImplementedException();
622 if (self_cause !=
self)
623 throw new java.
lang.IllegalStateException(
"Can't overwrite cause with " +
java.
util.Objects.toString(cause,
"a null"),
self);
626 throw new java.
lang.IllegalArgumentException(
"Self-causation not permitted",
self);
630 internal static void AddSuppressed(Exception
self, Exception e)
633 throw new NotImplementedException();
638 throw new java.
lang.IllegalArgumentException(
"Self-suppression not permitted", e);
640 throw new java.
lang.NullPointerException(
"Cannot suppress a null exception.");
648 if (_thisJava.suppressedExceptions ==
null)
651 if (_thisJava.suppressedExceptions ==
Throwable.SUPPRESSED_SENTINEL)
652 _thisJava.suppressedExceptions =
new java.
util.ArrayList();
654 _thisJava.suppressedExceptions.add(e);
660 internal static Exception[] GetSuppressed(Exception
self)
663 throw new NotImplementedException();
670 return EMPTY_THROWABLE_ARRAY;
674 if (t.suppressedExceptions ==
Throwable.SUPPRESSED_SENTINEL || t.suppressedExceptions ==
null)
675 return EMPTY_THROWABLE_ARRAY;
677 return (Exception[])t.suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
683 internal static int GetStackTraceDepth(Exception
self)
685 return GetOurStackTrace(
self).Length;
688 internal static object GetStackTraceElement(Exception
self,
int index)
690 return GetOurStackTrace(
self)[index];
700 internal static object[] GetOurStackTrace(Exception e)
703 throw new NotImplementedException();
709 ExceptionInfoHelper eih =
null;
711 if (data !=
null && !data.IsReadOnly)
713 eih = (ExceptionInfoHelper)data[EXCEPTION_DATA_KEY];
718 return eih.get_StackTrace(e);
725 if (
self.stackTrace ==
Throwable.UNASSIGNED_STACK || (
self.stackTrace ==
null && (
self.tracePart1 !=
null ||
self.tracePart2 !=
null)))
727 var eih =
new ExceptionInfoHelper(JVM.Context.ExceptionHelper,
self.tracePart1,
self.tracePart2);
728 self.stackTrace = eih.get_StackTrace(e);
729 self.tracePart1 =
null;
730 self.tracePart2 =
null;
734 return self.stackTrace ??
Throwable.UNASSIGNED_STACK;
746 internal static void SetStackTrace(Exception e,
object[] stackTrace)
749 throw new NotImplementedException();
753 for (
int i = 0; i < copy.Length; i++)
755 throw new java.
lang.NullPointerException();
757 JVM.Context.ExceptionHelper.SetStackTraceImpl(e, copy);
764 throw new NotImplementedException();
768 var eih =
new ExceptionInfoHelper(
this, stackTrace);
770 if (data !=
null && !data.IsReadOnly)
772 data[EXCEPTION_DATA_KEY] = eih;
778 if (t.stackTrace ==
null && t.tracePart1 ==
null && t.tracePart2 ==
null)
781 t.stackTrace = stackTrace;
795 internal static void FillInStackTrace(Exception e)
798 throw new NotImplementedException();
802 var eih =
new ExceptionInfoHelper(JVM.Context.ExceptionHelper,
null,
new StackTrace(
true));
804 if (data !=
null && !data.IsReadOnly)
806 data[EXCEPTION_DATA_KEY] = eih;
818 internal static void FixateException(Exception e)
821 throw new NotImplementedException();
823 JVM.Context.ExceptionHelper.FixateExceptionImpl(e);
826 void FixateExceptionImpl(Exception e)
829 throw new NotImplementedException();
831 exceptions.Add(e, NOT_REMAPPED);
835 internal static Exception UnmapException(Exception e)
838 throw new NotImplementedException();
840 return JVM.Context.ExceptionHelper.UnmapExceptionImpl(e);
844 Exception UnmapExceptionImpl(Exception e)
847 throw new NotImplementedException();
854 exceptions.Add(org, e);
864 Exception MapTypeInitializeException(TypeInitializationException t,
Type handler)
867 throw new NotImplementedException();
870 var r = MapException<Exception>(t.InnerException,
true,
false);
877 r =
new java.
lang.ExceptionInInitializerError(r.ToString());
881 var type = t.TypeName;
882 if (failedTypes.ContainsKey(type))
884 r =
new java.
lang.NoClassDefFoundError(
"Could not initialize class " + type);
888 if (handler !=
null && !handler.IsInstanceOfType(r))
891 failedTypes[type] = type;
895 ((
Throwable)r).setStackTrace(
new ExceptionInfoHelper(
this, t,
true).get_StackTrace(t));
902 bool IsInstanceOfType<T>(Exception t,
bool remap)
906 throw new NotImplementedException();
908 return remap || typeof(T) != typeof(Exception) ? t is T : t is not
Throwable;
913 internal T MapException<T>(Exception e,
bool remap,
bool unused)
917 throw new NotImplementedException();
920 var nonJavaException = e is not
Throwable;
921 if (nonJavaException && remap)
923 if (e is TypeInitializationException tie)
924 return (T)MapTypeInitializeException(tie, typeof(T));
926 exceptions.TryGetValue(e, out var obj);
928 if (remapped ==
null)
932 exceptions.Add(e, NOT_REMAPPED);
934 exceptions.Add(e, remapped);
938 else if (remapped != NOT_REMAPPED)
944 if (IsInstanceOfType<T>(e, remap))
948 if (!unused && t.tracePart1 ==
null && t.tracePart2 ==
null && t.stackTrace ==
Throwable.UNASSIGNED_STACK)
956 exceptions.Remove(org);
962 if (data !=
null && !data.IsReadOnly)
966 if (!data.Contains(EXCEPTION_DATA_KEY))
968 data.Add(EXCEPTION_DATA_KEY,
new ExceptionInfoHelper(
this, e,
true));
974 if (nonJavaException && !remap)
975 exceptions.Add(e, NOT_REMAPPED);