Skip to content

Instantly share code, notes, and snippets.

@kawasima
Created July 31, 2018 00:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kawasima/48696f0209029bd4e278f5a97315412f to your computer and use it in GitHub Desktop.
Save kawasima/48696f0209029bd4e278f5a97315412f to your computer and use it in GitHub Desktop.
参照渡しFake
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