From 4fd3e9d375d64d1fff5c8ddbe817cc97354e5fa7 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Fri, 9 Dec 2016 12:03:04 -0500 Subject: [PATCH] [class-parse] Support `class-parse --dump` on java.lang.Object Running `class-parse --dump` on `java.lang.Object` would fail: # on macOS, JDK 1.8 installed $ unzip /Library/Java/JavaVirtualMachines/jdk1.8.0_92.jdk/Contents/Home/jre/lib/rt.jar java/lang/Object.class $ mono class-parse.exe --dump java/lang/Object.class ... class-parse: Unable to read file 'java/lang/Object.class': Object reference not set to an instance of an object Enabling verbose output (`class-parse -v`) didn't help: $ mono class-parse.exe -v --dump java/lang/Object.class Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of the array. at Mono.Options.Option.Parse[T] (System.String value, Mono.Options.OptionContext c) [0x0005e] in <4d78dd3d6bb745d7a994cb7587b83fb2>:0 ... Doh! The problem with the `IndexOutOfRangeException` is a bug in `Mono.Options-PCL.cs`: it should be using `GenericTypeArguments[0]`, *not* `GenericTypeParameters[0]`. Fix that. Once that is fixed, we see that the `NullReferenceException` is coming from accessing `ClassFile.SuperClass.Name`, because `java.lang.Object` *has no superclass*, and thus `ClassFile.SuperClass` returns `null`. Properly check for that. With those changes in place, `class-parse --dump java.lang.Object` works as intended: $ mono class-parse.exe --dump java/lang/Object.class .class version: 52.0 ... Methods Count: 12 ... 11: finalize ()V Protected Code(10, Unknown[LineNumberTable](6)) Exceptions(java/lang/Throwable) --- tools/class-parse/Mono.Options-PCL.cs | 2 +- tools/class-parse/Program.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/class-parse/Mono.Options-PCL.cs b/tools/class-parse/Mono.Options-PCL.cs index 33c1588cf..32e71a265 100644 --- a/tools/class-parse/Mono.Options-PCL.cs +++ b/tools/class-parse/Mono.Options-PCL.cs @@ -530,7 +530,7 @@ protected static T Parse (string value, OptionContext c) bool nullable = ti.IsValueType && ti.IsGenericType && !ti.IsGenericTypeDefinition && tt.GetGenericTypeDefinition () == typeof(Nullable<>); - Type targetType = nullable ? tt.GetTypeInfo ().GenericTypeParameters [0] : typeof(T); + Type targetType = nullable ? tt.GetTypeInfo ().GenericTypeArguments [0] : typeof(T); //TypeConverter conv = TypeDescriptor.GetConverter (targetType); T t = default (T); try { diff --git a/tools/class-parse/Program.cs b/tools/class-parse/Program.cs index 43264d308..b7c4f5ed9 100644 --- a/tools/class-parse/Program.cs +++ b/tools/class-parse/Program.cs @@ -139,7 +139,7 @@ static void DumpClassFile (string file, TextWriter output) output.WriteLine ("\t{0}: {1}", i, c.ConstantPool [i]); } output.WriteLine ("ThisClass: {0}", c.ThisClass.Name); - output.WriteLine ("SuperClass: {0}", c.SuperClass.Name); + output.WriteLine ("SuperClass: {0}", c.SuperClass?.Name); output.WriteLine ("AccessFlags: {0}", c.AccessFlags); output.WriteLine ("Attributes Count: {0}", c.Attributes.Count); for (int i = 0; i < c.Attributes.Count; ++i) {