All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sql2o.reflection.UnsafeFieldGetterFactory Maven / Gradle / Ivy

There is a newer version: 0.2.6
Show newest version
package org.sql2o.reflection;

import org.sql2o.Sql2oException;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

/**
 * @author mdelapenya
 */
@SuppressWarnings("Unsafe")
public class UnsafeFieldGetterFactory implements FieldGetterFactory, ObjectConstructorFactory {
    private final static Unsafe theUnsafe;

    static {
        try {
            Class unsafeClass   = Class.forName("sun.misc.Unsafe");
            Field declaredField = unsafeClass.getDeclaredField("theUnsafe");
            declaredField.setAccessible(true);
            theUnsafe = (Unsafe) declaredField.get(null);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }

    public Getter newGetter(final Field field) {
        final Class   type     = field.getType();
        final boolean isStatic = Modifier.isStatic(field.getModifiers());

        final long offset = isStatic
                ? theUnsafe.staticFieldOffset(field)
                : theUnsafe.objectFieldOffset(field);

        if (!Modifier.isVolatile(field.getModifiers())) {
            if (type == Boolean.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getBoolean(obj, offset);
                    }

                    public Class getType() {
                        return Boolean.TYPE;
                    }
                };
            }

            if (type == Character.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getChar(obj, offset);
                    }

                    public Class getType() {
                        return Character.TYPE;
                    }
                };
            }

            if (type == Byte.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getByte(obj, offset);
                    }

                    public Class getType() {
                        return Byte.TYPE;
                    }
                };
            }

            if (type == Short.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getShort(obj, offset);
                    }

                    public Class getType() {
                        return Short.TYPE;
                    }
                };
            }

            if (type == Integer.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getInt(obj, offset);
                    }

                    public Class getType() {
                        return Integer.TYPE;
                    }
                };
            }

            if (type == Long.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getLong(obj, offset);
                    }

                    public Class getType() {
                        return Long.TYPE;
                    }
                };
            }

            if (type == Float.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getFloat(obj, offset);
                    }

                    public Class getType() {
                        return Float.TYPE;
                    }
                };
            }
            if (type == Double.TYPE) {
                return new Getter() {
                    public Object getProperty(Object obj) {
                        return theUnsafe.getDouble(obj, offset);
                    }

                    public Class getType() {
                        return Double.TYPE;
                    }
                };
            }
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getObject(obj, offset);
                }

                public Class getType() {
                    return type;
                }
            };
        }

        if (type == Boolean.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getBooleanVolatile(obj, offset);
                }

                public Class getType() {
                    return Boolean.TYPE;
                }
            };
        }
        if (type == Character.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getCharVolatile(obj, offset);
                }

                public Class getType() {
                    return Character.TYPE;
                }
            };
        }
        if (type == Byte.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getByteVolatile(obj, offset);
                }

                public Class getType() {
                    return Byte.TYPE;
                }
            };
        }
        if (type == Short.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getShortVolatile(obj, offset);
                }

                public Class getType() {
                    return Short.TYPE;
                }
            };
        }
        if (type == Integer.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getIntVolatile(obj, offset);
                }

                public Class getType() {
                    return Integer.TYPE;
                }
            };
        }
        if (type == Long.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getLongVolatile(obj, offset);
                }

                public Class getType() {
                    return Long.TYPE;
                }
            };
        }
        if (type == Float.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getFloatVolatile(obj, offset);
                }

                public Class getType() {
                    return Float.TYPE;
                }
            };
        }
        if (type == Double.TYPE) {
            return new Getter() {
                public Object getProperty(Object obj) {
                    return theUnsafe.getDoubleVolatile(obj, offset);
                }

                public Class getType() {
                    return Double.TYPE;
                }
            };
        }
        return new Getter() {
            public Object getProperty(Object obj) {
                return theUnsafe.getObjectVolatile(obj, offset);
            }

            public Class getType() {
                return type;
            }
        };
    }

    public ObjectConstructor newConstructor(final Class clazz) {
        return getConstructor(clazz);
    }

    public static ObjectConstructor getConstructor(final Class clazz) {
        return () -> {
            try {
                return theUnsafe.allocateInstance(clazz);
            } catch (InstantiationException e) {
                throw new Sql2oException("Could not create a new instance of class " + clazz, e);
            }
        };
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy