From 3d12866dc20dc55d487ef8b3f1303e30293f438b Mon Sep 17 00:00:00 2001
From: FuckYou <gabriel.tofvesson@gmail.com>
Date: Sun, 5 Mar 2017 01:13:19 +0100
Subject: [PATCH] Minor update - Added support for immediately posting values
 without async starting - Added method to safely set field values. It handles
 cases of static- or object-fields   - A note has been added to the JavaDoc.
 If you are considering using this method, please read the JavaDoc as it
 contains some vital information - Properly defined the IgnorantRunnable -
 Replaced all calls to sun.misc.Unsafe.putBoolean() with putInt() to support
 Android

---
 src/com/tofvesson/async/Async.java            |  9 ++-
 src/com/tofvesson/async/IgnorantRunnable.java |  4 +-
 .../tofvesson/reflection/SafeReflection.java  | 65 ++++++++++++++-----
 3 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/src/com/tofvesson/async/Async.java b/src/com/tofvesson/async/Async.java
index 234d246..f286b6f 100644
--- a/src/com/tofvesson/async/Async.java
+++ b/src/com/tofvesson/async/Async.java
@@ -2,7 +2,7 @@ package com.tofvesson.async;
 
 import java.lang.reflect.*;
 
-@SuppressWarnings({"WeakerAccess", "unused", "unchecked"})
+@SuppressWarnings({"WeakerAccess", "unused", "unchecked", "SameParameterValue"})
 public class Async<T> implements Awaitable{
 
     /**
@@ -158,6 +158,13 @@ public class Async<T> implements Awaitable{
      */
     public Async(Constructor<T> c){ this(c, (Object[]) null); }
 
+    /**
+     * Should probably only be used in debugging applications when a preset return value should be given and there is no need to start a new thread.
+     * This won't even start a new thread. All it does is set it's current state to "finished" and allow for the return value to be read.
+     * @param o Return value.
+     */
+    public Async(T o){ complete = true; ret = o; }
+
     /**
      * WARNING: Package-scoped because it should only be used when overriding standard construction. Should not bw used haphazardly!
      */
diff --git a/src/com/tofvesson/async/IgnorantRunnable.java b/src/com/tofvesson/async/IgnorantRunnable.java
index c4cecec..52cdd92 100644
--- a/src/com/tofvesson/async/IgnorantRunnable.java
+++ b/src/com/tofvesson/async/IgnorantRunnable.java
@@ -4,6 +4,6 @@ package com.tofvesson.async;
  * A Runnable-esque interface that allows for running code without try-catch blocks.
  */
 public abstract class IgnorantRunnable implements Runnable{
-    public void run(){ try { irun(); } catch (Throwable throwable) { throw new RuntimeException(throwable); } }
-    abstract void irun() throws Throwable;
+    public final void run(){ try { irun(); } catch (Throwable throwable) { throw new RuntimeException(throwable); } }
+    public abstract void irun() throws Throwable;
 }
diff --git a/src/com/tofvesson/reflection/SafeReflection.java b/src/com/tofvesson/reflection/SafeReflection.java
index 784b49c..106bc3b 100644
--- a/src/com/tofvesson/reflection/SafeReflection.java
+++ b/src/com/tofvesson/reflection/SafeReflection.java
@@ -8,11 +8,13 @@ import java.util.*;
 /**
  * Safe tools to help simplify code when dealing with reflection.
  */
+@SuppressWarnings({"unused", "SameParameterValue", "UnusedReturnValue"})
 public final class SafeReflection {
 
 
-    private static final Unsafe unsafe;
+    public static final Unsafe unsafe;
     private static final Method newInstance, aConAccess;
+    private static final Field modifiers;
     private static final String version;
     private static final long override;
     private static final boolean hasAConAccess;
@@ -20,7 +22,7 @@ public final class SafeReflection {
     static{
         Unsafe u = null;
         Method m = null, m1 = null;
-        Field f;
+        Field f = null;
         long l = 0;
         String ver = "";
         boolean b = true;
@@ -34,23 +36,30 @@ public final class SafeReflection {
             f = Unsafe.class.getDeclaredField("theUnsafe");
             f.setAccessible(true);
             u = (Unsafe) f.get(null);
-            l=u.objectFieldOffset(AccessibleObject.class.getDeclaredField("override"));
+            f = Field.class.getDeclaredField("modifiers");
+            f.setAccessible(true);
+            try {
+                l = u.objectFieldOffset(AccessibleObject.class.getDeclaredField("override")); // Most desktop versions of Java
+            }catch(Exception e){
+                l = u.objectFieldOffset(AccessibleObject.class.getDeclaredField("flag")); // God-damned Android
+            }
             try {
                 m1 = Constructor.class.getDeclaredMethod("acquireConstructorAccessor");
                 m1.setAccessible(true);
                 m = Class.forName(ver + ".DelegatingConstructorAccessorImpl").getDeclaredMethod("newInstance", Object[].class);
-                u.putBoolean(m, l, true);
+                u.putInt(m, l, 1);
             }catch(Exception e){
                 b = false;
             }
-            u.putBoolean(f, l, true);
-        }catch(Exception ignored){ ignored.printStackTrace(); }                                                                                     // Exception is never thrown
+            u.putInt(f, l, 1);
+        }catch(Exception ignored){ ignored.printStackTrace(); }                                                         // Exception is never thrown
         unsafe = u;
         newInstance = m;
         aConAccess = m1;
         override = l;
         version = ver;
         hasAConAccess = b;
+        modifiers = f;
     }
 
     /**
@@ -63,7 +72,7 @@ public final class SafeReflection {
     public static <T> Constructor<T> getConstructor(Class<T> c, Class<?>... params){
         try{
             Constructor<T> c1 = c.getConstructor(params);
-            unsafe.putBoolean(c1, override, true);
+            unsafe.putInt(c1, override, 1);
             return c1;
         }catch(Exception e){}
         return null;
@@ -79,7 +88,7 @@ public final class SafeReflection {
         try {
             @SuppressWarnings("unchecked")
             Constructor<T> c1 = (Constructor<T>) c.getDeclaredConstructors()[0];
-            unsafe.putBoolean(c1, override, true);
+            unsafe.putInt(c1, override, 1);
             return c1;
         }catch (Exception e){}
         return null;
@@ -96,7 +105,7 @@ public final class SafeReflection {
     public static Method getMethod(Class<?> c, String name, Class<?>... params){
         try{
             Method m = c.getDeclaredMethod(name, params);
-            unsafe.putBoolean(m, override, true);
+            unsafe.putInt(m, override, 1);
             return m;
         }catch(Exception e){}
         return null;
@@ -121,7 +130,7 @@ public final class SafeReflection {
      * @return Return value of method or null if method is null.
      */
     public static Object invokeMethod(Object inst, Method m, Object... params){
-        if(m!=null) unsafe.putBoolean(m, override, true);
+        if(m!=null) unsafe.putInt(m, override, 1);
         try{ return m!=null?m.invoke(inst, params):null; }catch(Exception e){}
         return null;
     }
@@ -157,7 +166,7 @@ public final class SafeReflection {
     public static Method getFirstMethod(Class<?> c, String name){
         try{
             Method[] m = c.getDeclaredMethods();
-            for (Method aM : m) if(aM.getName().equals(name)){ unsafe.putBoolean(aM, override, true); return aM;}
+            for (Method aM : m) if(aM.getName().equals(name)){ unsafe.putInt(aM, override, 1); return aM;}
         }catch(Exception e){}
         return null;
     }
@@ -171,7 +180,7 @@ public final class SafeReflection {
     public static Field getField(Class<?> c, String name){
         try{
             Field f = c.getDeclaredField(name);
-            unsafe.putBoolean(f, override, true);
+            unsafe.putInt(f, override, 1);
             return f;
         }catch(Exception e){}
         return null;
@@ -201,6 +210,28 @@ public final class SafeReflection {
         return null;
     }
 
+    /**
+     * Set field to specified value.
+     * <br><h1 style="text-align: center; color: red;">Please note:</h1>A JIT compiler may inline private final fields in methods which will prevent the actual value
+     * from changing at runtime.<br>This means that the value stored in the field <i>will</i> be changed, but any methods referring directly
+     * (not by java.lang.reflect.Field or sun.misc.Unsafe) to the field in the source will not be affected.
+     * This should only happen, though, if the field isn't set during runtime i.e. in a static block or constructor. This means that only fields that are truly constant
+     * like<br>"<i>public static final boolean b = false;</i>"<br>might be problematic.
+     * @param inv Object whose field to set the value of. Can be null.
+     * @param f Field to modify.
+     * @param value Value to set the field to.
+     * @return True if setting value succeeded.
+     */
+    public static boolean setFieldValue(Object inv, Field f, Object value){
+        try{
+            unsafe.putInt(f, override, 1); // Ensure field override flag is set
+            if(Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) modifiers.setInt(f, f.getModifiers() &~ Modifier.FINAL);
+            f.set(inv, value);
+            return true;
+        }catch(Exception e){ e.printStackTrace(); }
+        return false;
+    }
+
     /**
      * Gets a reference to the enclosing class from a defined inner (nested) object.
      * @param nested Object instance of a nested class.
@@ -209,7 +240,7 @@ public final class SafeReflection {
     public static Object getEnclosingClassObjectRef(Object nested){
         try{
             Field f = nested.getClass().getDeclaredField("this$0");
-            unsafe.putBoolean(f, override, true);
+            unsafe.putInt(f, override, 1);
             return f.get(nested);
         }catch(Exception e){}
         return null;
@@ -243,7 +274,7 @@ public final class SafeReflection {
             if(def==null) def = new EnumDefinition();
             // Get a reference to the static method values() and get values
             Method v = clazz.getDeclaredMethod("values");
-            unsafe.putBoolean(v, override, true);
+            unsafe.putInt(v, override, 1);
             T[] values = (T[]) v.invoke(null);
 
             // Return object if it already exists
@@ -258,7 +289,7 @@ public final class SafeReflection {
 
             // Get enum constructor (inherited from Enum.class)
             Constructor<T> c = clazz.getDeclaredConstructor(paramList);
-            if(hasAConAccess) unsafe.putBoolean(c, override, true);
+            if(hasAConAccess) unsafe.putInt(c, override, 1);
             else c.setAccessible(true);
 
             Object[] parameters = new Object[def.params.size()+2];
@@ -307,6 +338,7 @@ public final class SafeReflection {
     /**
      * A definition for custom enum creation.
      */
+    @SuppressWarnings("UnusedReturnValue")
     public static final class EnumDefinition {
         HashMap<Object, Class> params = new HashMap<Object, Class>(); // Assign a specific type to each parameter
 
@@ -342,7 +374,7 @@ public final class SafeReflection {
          * @param b Boolean parameter.
          * @return A reference to the EnumDefinition object this method was called on (for chaining).
          */
-        public EnumDefinition putBoolean(boolean b){
+        public EnumDefinition putInt(boolean b){
             try { return putPrimitive(b);  } catch (NotAutoBoxedException e) { }
             return this;
         }
@@ -458,5 +490,4 @@ public final class SafeReflection {
         }
         return s;
     }
-
 }