Update DexMaker's UnsafeAllocator

Bug: 8297650
Change-Id: Icab2ac88926086070b1600e4514872d8b05de261
diff --git a/README b/README
index 270e5dd..5a1551c 100644
--- a/README
+++ b/README
@@ -14,5 +14,9 @@
 It includes a stock code generator for class proxies. If you just want to do AOP or class mocking, you don't need to mess around with bytecodes.
 
 Local Modifications:
-Patch to fix http://b/8108255 (Some mockito-based cannot be initialized due to a classloader issue), while Dexmaker's issue #20 (https://code.google.com/p/dexmaker/issues/detail?id=20) is not fixed. 
+bug-8108255.patch: temporary workaround to ClassLoading issues
+    (see https://code.google.com/p/dexmaker/issues/detail?id=20)
+bug-8297650.patch: temporary workaround for a breakage in object instantiation
+    (see https://code.google.com/p/dexmaker/issues/detail?id=22)
+
 (to apply, run 'patch -p0 < bug-xyz.patch' from a fresh src)
diff --git a/bug-8297650.patch b/bug-8297650.patch
new file mode 100644
index 0000000..59d4d32
--- /dev/null
+++ b/bug-8297650.patch
@@ -0,0 +1,39 @@
+--- src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java
++++ src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java
+@@ -92,6 +92,29 @@ abstract class UnsafeAllocator {
+         } catch (Exception ignored) {
+         }
+ 
++        // try dalvikvm, with change https://android-review.googlesource.com/#/c/52331/
++        // public class ObjectStreamClass {
++        //   private static native long getConstructorId(Class<?> c);
++        //   private static native Object newInstance(Class<?> instantiationClass, long methodId);
++        // }
++        try {
++            Method getConstructorId = ObjectStreamClass.class
++                    .getDeclaredMethod("getConstructorId", Class.class);
++            getConstructorId.setAccessible(true);
++            final long constructorId = (Long) getConstructorId.invoke(null, Object.class);
++            final Method newInstance = ObjectStreamClass.class
++                    .getDeclaredMethod("newInstance", Class.class, long.class);
++            newInstance.setAccessible(true);
++            return new UnsafeAllocator() {
++                @Override
++                @SuppressWarnings("unchecked")
++                public <T> T newInstance(Class<T> c) throws Exception {
++                    return (T) newInstance.invoke(null, c, constructorId);
++                }
++            };
++        } catch (Exception ignored) {
++        }
++
+         // give up
+         return new UnsafeAllocator() {
+             @Override
+@@ -100,4 +123,4 @@ abstract class UnsafeAllocator {
+             }
+         };
+     }
+-}
+\ No newline at end of file
++}
diff --git a/src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java b/src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java
index 2e10b41..15e0324 100644
--- a/src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java
+++ b/src/mockito/java/com/google/dexmaker/mockito/UnsafeAllocator.java
@@ -92,6 +92,29 @@
         } catch (Exception ignored) {
         }
 
+        // try dalvikvm, with change https://android-review.googlesource.com/#/c/52331/
+        // public class ObjectStreamClass {
+        //   private static native long getConstructorId(Class<?> c);
+        //   private static native Object newInstance(Class<?> instantiationClass, long methodId);
+        // }
+        try {
+            Method getConstructorId = ObjectStreamClass.class
+                    .getDeclaredMethod("getConstructorId", Class.class);
+            getConstructorId.setAccessible(true);
+            final long constructorId = (Long) getConstructorId.invoke(null, Object.class);
+            final Method newInstance = ObjectStreamClass.class
+                    .getDeclaredMethod("newInstance", Class.class, long.class);
+            newInstance.setAccessible(true);
+            return new UnsafeAllocator() {
+                @Override
+                @SuppressWarnings("unchecked")
+                public <T> T newInstance(Class<T> c) throws Exception {
+                    return (T) newInstance.invoke(null, c, constructorId);
+                }
+            };
+        } catch (Exception ignored) {
+        }
+
         // give up
         return new UnsafeAllocator() {
             @Override
@@ -100,4 +123,4 @@
             }
         };
     }
-}
\ No newline at end of file
+}