JdbcMapper/beehive-jdbc-mapper/src/test/java/com/moparisthebest/jdbc/dto/FinalDTO.java

193 lines
6.3 KiB
Java

package com.moparisthebest.jdbc.dto;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* This class is meant to test the java compiler's in-lining behavior for final variables
*/
public class FinalDTO {
private static final boolean useReflectionNotUnsafe = true;
private final long finalPrimitiveLongDirect = 2L;
private long effectiveFinalPrimitiveLongDirect = 2L;
private final long finalPrimitiveLongConstructor;
{
this.finalPrimitiveLongConstructor = 2L;
}
private final String finalStringDirect = "2";
private String effectiveFinalStringDirect = "2";
private final String finalStringConstructor;
{
this.finalStringConstructor = "2";
}
private final Long finalLongDirect = 2L;
private final Long finalLongConstructor;
{
this.finalLongConstructor = 2L;
}
public long getFinalPrimitiveLongDirect() {
return finalPrimitiveLongDirect;
}
public long getEffectiveFinalPrimitiveLongDirect() {
return effectiveFinalPrimitiveLongDirect;
}
public long getFinalPrimitiveLongConstructor() {
return finalPrimitiveLongConstructor;
}
public String getFinalStringDirect() {
return finalStringDirect;
}
public String getEffectiveFinalStringDirect() {
return effectiveFinalStringDirect;
}
public String getFinalStringConstructor() {
return finalStringConstructor;
}
public Long getFinalLongDirect() {
return finalLongDirect;
}
public Long getFinalLongConstructor() {
return finalLongConstructor;
}
@Override
public String toString() {
return "FinalTest{" +
"finalPrimitiveLongDirect=" + finalPrimitiveLongDirect +
", reflection finalPrimitiveLongDirect=" + getField("finalPrimitiveLongDirect") +
", effectiveFinalPrimitiveLongDirect=" + effectiveFinalPrimitiveLongDirect +
", reflection effectiveFinalPrimitiveLongDirect=" + getField("effectiveFinalPrimitiveLongDirect") +
", finalPrimitiveLongConstructor=" + finalPrimitiveLongConstructor +
", reflection finalPrimitiveLongConstructor=" + getField("finalPrimitiveLongConstructor") +
", finalStringDirect=" + finalStringDirect +
", reflection finalStringDirect=" + getField("finalStringDirect") +
", effectiveFinalStringDirect=" + effectiveFinalStringDirect +
", reflection effectiveFinalStringDirect=" + getField("effectiveFinalStringDirect") +
", finalStringConstructor=" + finalStringConstructor +
", reflection finalStringConstructor=" + getField("finalStringConstructor") +
", finalLongDirect=" + finalLongDirect +
", reflection finalLongDirect=" + getField("finalLongDirect") +
", finalLongConstructor=" + finalLongConstructor +
", reflection finalLongConstructor=" + getField("finalLongConstructor") +
'}';
}
public boolean directEqualsReflection() {
return directEqualsReflection(finalPrimitiveLongDirect, "finalPrimitiveLongDirect")
&& directEqualsReflection(effectiveFinalPrimitiveLongDirect, "effectiveFinalPrimitiveLongDirect")
&& directEqualsReflection(finalPrimitiveLongConstructor, "finalPrimitiveLongConstructor")
&& directEqualsReflection(finalStringDirect, "finalStringDirect")
&& directEqualsReflection(effectiveFinalStringDirect, "effectiveFinalStringDirect")
&& directEqualsReflection(finalStringConstructor, "finalStringConstructor")
&& directEqualsReflection(finalLongDirect, "finalLongDirect")
&& directEqualsReflection(finalLongConstructor, "finalLongConstructor")
;
}
private boolean directEqualsReflection(final Object object, final String fieldName) {
return equals(object, getField(fieldName));
}
public Object getField(final String fieldName) {
return getField(this, fieldName);
}
public boolean setField(final String fieldName, final Object fieldValue) {
setField(this, fieldName, fieldValue);
return directEqualsReflection();
}
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
private static Object getField(final Object object, final String fieldName) {
try {
final Field field = object.getClass().getDeclaredField(fieldName);
if (useReflectionNotUnsafe) {
field.setAccessible(true);
return field.get(object);
} else {
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
final Unsafe unsafe = (Unsafe) unsafeField.get(null);
final long offset = unsafe.objectFieldOffset(field);
if (field.getType().isPrimitive()) {
if (field.getType().equals(long.class))
return unsafe.getLong(object, offset);
else
throw new RuntimeException("unsupported primitive type");
} else
return unsafe.getObject(object, offset);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private static void setField(final Object object, final String fieldName, final Object fieldValue) {
try {
final Field field = object.getClass().getDeclaredField(fieldName);
if (useReflectionNotUnsafe) {
field.setAccessible(true);
field.set(object, fieldValue);
} else {
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
final Unsafe unsafe = (Unsafe) unsafeField.get(null);
final long offset = unsafe.objectFieldOffset(field);
if (field.getType().isPrimitive()) {
if (fieldValue instanceof Long)
unsafe.putLong(object, offset, (Long) fieldValue);
else
throw new RuntimeException("unsupported primitive type");
} else
unsafe.putObject(object, offset, fieldValue);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
public static void main(final String[] args) {
final FinalDTO object = new FinalDTO();
System.out.println("1: " + object);
setField(object, "finalPrimitiveLongDirect", 1L);
System.out.println("2: " + object);
setField(object, "finalPrimitiveLongConstructor", 1L);
System.out.println("3: " + object);
setField(object, "finalStringDirect", "1");
System.out.println("4: " + object);
setField(object, "finalStringConstructor", "1");
System.out.println("5: " + object);
setField(object, "finalLongDirect", 1L);
System.out.println("6: " + object);
setField(object, "finalLongConstructor", 1L);
System.out.println("7: " + object);
setField(object, "effectiveFinalPrimitiveLongDirect", 1L);
System.out.println("8: " + object);
setField(object, "effectiveFinalStringDirect", "1");
System.out.println("9: " + object);
}
}