Created
July 31, 2018 00:27
-
-
Save kawasima/48696f0209029bd4e278f5a97315412f to your computer and use it in GitHub Desktop.
参照渡しFake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package sandbox; | |
import org.junit.Before; | |
import org.junit.Test; | |
import sun.misc.Unsafe; | |
import java.lang.reflect.Constructor; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import java.util.ArrayList; | |
import java.util.HashSet; | |
import java.util.List; | |
public class UnsafeTest { | |
Unsafe unsafe; | |
@Before | |
public void setup() throws Exception { | |
Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor(); | |
unsafeConstructor.setAccessible(true); | |
unsafe = unsafeConstructor.newInstance(); | |
} | |
public void modifyList(List<String> langs) throws Exception { | |
long dest = toAddress(langs); | |
langs = new ArrayList<>(); | |
langs.add("PHP"); | |
long src = toAddress(langs); | |
long size = sizeOf(langs); | |
unsafe.copyMemory(src, dest, size); | |
} | |
@Test | |
public void testReference() throws Exception { | |
List<String> langs = new ArrayList<>(); | |
langs.add("Java"); | |
modifyList(langs); | |
System.out.println(langs); // -> ["PHP"] | |
} | |
private long normalize(int value) { | |
if(value >= 0) return value; | |
return (~0L >>> 32) & value; | |
} | |
private long sizeOf(Object o) { | |
HashSet<Field> fields = new HashSet<Field>(); | |
Class c = o.getClass(); | |
while (c != Object.class) { | |
for (Field f : c.getDeclaredFields()) { | |
if ((f.getModifiers() & Modifier.STATIC) == 0) { | |
fields.add(f); | |
} | |
} | |
c = c.getSuperclass(); | |
} | |
// get offset | |
long maxSize = 0; | |
for (Field f : fields) { | |
long offset = unsafe.objectFieldOffset(f); | |
if (offset > maxSize) { | |
maxSize = offset; | |
} | |
} | |
return ((maxSize/8) + 1) * 8; // padding | |
} | |
private long toAddress(Object obj) { | |
Object[] array = new Object[] {obj}; | |
long baseOffset = unsafe.arrayBaseOffset(Object[].class); | |
return normalize(unsafe.getInt(array, baseOffset)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment