io.github.jdcmp.codegen.Instantiators Maven / Gradle / Ivy
package io.github.jdcmp.codegen;
import io.github.jdcmp.api.documentation.ThreadSafe;
import io.github.jdcmp.codegen.customization.AvailableInstantiator;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;
@ThreadSafe
final class Instantiators {
private static final Logger LOGGER = Logger.getLogger(Instantiators.class.getName());
static List create(Collection available) {
ArrayList instantiators = new ArrayList<>(4);
create(available, instantiators, AvailableInstantiator.UNSAFE, UnsafeInstantiator::new);
create(available, instantiators, AvailableInstantiator.REFLECTION_FACTORY, ReflectionFactoryInstantiator::new);
create(available, instantiators, AvailableInstantiator.REFLECTION_FACTORY, ReflectionFactoryConstructorInstantiator::new);
create(available, instantiators, AvailableInstantiator.CONSTRUCTOR, ConstructorInstantiator::new);
return instantiators;
}
private static void create(
Collection available,
ArrayList list,
AvailableInstantiator wanted,
Callable extends Instantiator> factory) {
if (available.contains(wanted)) {
try {
list.add(factory.call());
} catch (Exception e) {
LOGGER.log(Level.FINE, "Failed to load Instantiator: " + wanted, e);
}
}
}
private static final class UnsafeInstantiator implements Instantiator {
UnsafeInstantiator() {
Utils.initializeClass(Holder.class);
}
@Override
public boolean requiresConstructor() {
return false;
}
@Override
public boolean supportsVmAnonOrHiddenClasses() {
return true;
}
@SuppressWarnings("unchecked")
@Override
public T newInstance(Class extends T> clazz) {
try {
Object instance = (Object) Holder.ALLOCATE_INSTANCE.invokeExact(clazz);
return (T) instance;
} catch (@SuppressWarnings("removal") ThreadDeath e) {
throw e;
} catch (Throwable e) {
throw InstantiationException.forClass(clazz, e);
}
}
private static final class Holder {
static final MethodHandle ALLOCATE_INSTANCE;
static {
ALLOCATE_INSTANCE = Internals.Unsafe.Method.ALLOCATE_INSTANCE.find().bindTo(Internals.Unsafe.getInstance());
}
}
}
private static final class ReflectionFactoryInstantiator implements Instantiator {
ReflectionFactoryInstantiator() {
Utils.initializeClass(Holder.class);
}
@Override
public boolean requiresConstructor() {
return false;
}
@Override
public boolean supportsVmAnonOrHiddenClasses() {
return false;
}
@SuppressWarnings("unchecked")
@Override
public T newInstance(Class extends T> clazz) {
Constructor extends T> constructor;
try {
MethodHandle method = Holder.NEW_CONSTRUCTOR_FOR_SERIALIZATION;
constructor = (Constructor extends T>) method.invokeExact(clazz);
} catch (@SuppressWarnings("removal") ThreadDeath e) {
throw e;
} catch (Throwable e) {
throw new RuntimeException("Failed to create serialization constructor for class: " + clazz, e);
}
if (constructor == null) {
throw new RuntimeException("The constructor returned by newConstructorForSerialization is null.");
}
try {
return constructor.newInstance();
} catch (Exception e) {
throw InstantiationException.forClass(clazz, e);
}
}
private static final class Holder {
static final MethodHandle NEW_CONSTRUCTOR_FOR_SERIALIZATION;
static {
MethodHandle newConstructorForSerialization = Internals.ReflectionFactory.Method.NEW_CONSTRUCTOR_FOR_SERIALIZATION.find();
Object reflectionFactory = Internals.ReflectionFactory.getInstance();
NEW_CONSTRUCTOR_FOR_SERIALIZATION = newConstructorForSerialization.bindTo(reflectionFactory);
}
}
}
private static final class ReflectionFactoryConstructorInstantiator implements Instantiator {
ReflectionFactoryConstructorInstantiator() {
Utils.initializeClass(Holder.class);
}
@Override
public boolean requiresConstructor() {
return false;
}
@Override
public boolean supportsVmAnonOrHiddenClasses() {
return false;
}
@SuppressWarnings("unchecked")
@Override
public T newInstance(Class extends T> clazz) {
Constructor extends T> constructor;
try {
Constructor
© 2015 - 2024 Weber Informatics LLC | Privacy Policy