
ru.progrm_jarvis.javacommons.invoke.FullAccessLookupFactories Maven / Gradle / Ivy
package ru.progrm_jarvis.javacommons.invoke;
import lombok.experimental.UtilityClass;
import lombok.val;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.progrm_jarvis.javacommons.object.Result;
import ru.progrm_jarvis.javacommons.unsafe.UnsafeInternals;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Optional;
/**
* Utility for accessing {@link LookupFactory lookup factories} giving practically full access.
*/
@UtilityClass
public class FullAccessLookupFactories {
private final @Nullable LookupFactory LOOKUP_FACTORY;
static {
final Lookup rootLookup;
LOOKUP_FACTORY = (rootLookup = rootFullAccessLookup()) == null ? null : rootLookup::in;
}
/**
* Gets the default {@link LookupFactory lookup factory}.
*
* @return the default optional {@link LookupFactory lookup factory}.
*/
public Optional getDefault() {
return Optional.ofNullable(LOOKUP_FACTORY);
}
/**
* Attempts to create the root lookup with full access.
*
* @return optional containing the created full-access lookup
* or an {@link Optional#empty() empty optional} if it cannot be created
*/
private @Nullable Lookup rootFullAccessLookup() {
// Method 1: Find Lookup#IMPL_LOOKUP
{
final Field implLookupField = Arrays.stream(Lookup.class.getDeclaredFields())
.filter(field -> Modifier.isStatic(field.getModifiers())
&& field.getName().equals("IMPL_LOOKUP")
&& Lookup.class.isAssignableFrom(field.getType())
)
.findAny()
.orElse(null);
if (implLookupField == null) return null;
// Get the field
// Attempt 1: legacy variant: via `setAccessible`, start from it as it is does not require Unsafe
{
@SuppressWarnings("deprecation") val accessible = implLookupField.isAccessible();
try {
try {
implLookupField.setAccessible(true);
} catch (final RuntimeException e) {
// InaccessibleObjectException reports inaccessibility via reflection, thus go to #2
// all other RuntimeExceptions should just be rethrown
// the known error class is available only since Java 9
if (!e.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException"))
return null;
}
try {
return (Lookup) implLookupField.get(null);
} catch (final IllegalAccessException ignored) {} // at least we tried
} finally {
implLookupField.setAccessible(accessible);
}
}
// Attempt 2: more up-to-date variant which yet relies on Unsafe
final Result
© 2015 - 2025 Weber Informatics LLC | Privacy Policy