(@NonNull Object obj)
| 16 | } |
| 17 | |
| 18 | @SuppressLint("DiscouragedPrivateApi") |
| 19 | @NonNull |
| 20 | public static Object shadowClone(@NonNull Object obj) { |
| 21 | Class<?> klass = obj.getClass(); |
| 22 | Class<?> kUnsafe; |
| 23 | Object theUnsafe; |
| 24 | Method allocateInstance; |
| 25 | try { |
| 26 | kUnsafe = Class.forName("sun.misc.Unsafe"); |
| 27 | theUnsafe = kUnsafe.getDeclaredField("theUnsafe").get(null); |
| 28 | allocateInstance = kUnsafe.getDeclaredMethod("allocateInstance", Class.class); |
| 29 | } catch (ReflectiveOperationException e) { |
| 30 | throw IoUtils.unsafeThrow(e); |
| 31 | } |
| 32 | Object instance; |
| 33 | try { |
| 34 | instance = allocateInstance.invoke(theUnsafe, klass); |
| 35 | assert instance != null; |
| 36 | } catch (IllegalAccessException | InvocationTargetException e) { |
| 37 | throw IoUtils.unsafeThrowForIteCause(e); |
| 38 | } |
| 39 | Class<?> current = klass; |
| 40 | while ((current = current.getSuperclass()) != null) { |
| 41 | if (current == Object.class) { |
| 42 | break; |
| 43 | } |
| 44 | for (Field f : current.getDeclaredFields()) { |
| 45 | // skip static and transient fields |
| 46 | if ((f.getModifiers() & (Modifier.STATIC | Modifier.TRANSIENT)) != 0) { |
| 47 | continue; |
| 48 | } |
| 49 | f.setAccessible(true); |
| 50 | try { |
| 51 | f.set(instance, f.get(obj)); |
| 52 | } catch (IllegalAccessException e) { |
| 53 | throw new AssertionError(e); |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | return instance; |
| 58 | } |
| 59 | } |
nothing calls this directly
no test coverage detected