A driver to allow deep interaction with the JVM without any restrictions
Extracted from Burningwave Core 8, fully refactored and with an extensible architecture the JVM Driver allows a deep interaction with the JVM without any restrictions.
To include ToolFactory JVM Driver in your projects simply use with Apache Maven:
<dependency>
<groupId>io.github.toolfactory</groupId>
<artifactId>jvm-driver</artifactId>
<version>9.7.1</version>
</dependency>
To use ToolFactory JMV Driver as a Java module, add the following to your module-info.java
:
//Mandatory if you use the dynamic, hybrid or native driver
requires io.github.toolfactory.narcissus;
//Mandatory if you use the default, dynamic or hybrid driver
requires jdk.unsupported;
requires io.github.toolfactory.jvm;
There are four kinds of driver:
By default all JNI methods used by the dynamic, hybrid and native driver are supplied by Narcissus that works on the following system configurations:
It is also possible to replace the Narcissus JNI engine with another fast JNI engine: the one included in the Burningwave JVM Driver.
To create a driver instance you should use this code:
io.github.toolfactory.jvm.Driver driver = io.github.toolfactory.jvm.Driver.getNew();
The driver type returned by the method io.github.toolfactory.jvm.Driver.Factory.getNew()
is the first driver that can be initialized among the default, hybrid and native drivers respectively.
If you need to create a specific driver type you should use:
io.github.toolfactory.jvm.Driver driver = io.github.toolfactory.jvm.Driver.Factory.getNewDefault();
io.github.toolfactory.jvm.Driver driver = io.github.toolfactory.jvm.Driver.Factory.getNewDynamic();
io.github.toolfactory.jvm.Driver driver = io.github.toolfactory.jvm.Driver.Factory.getNewHybrid();
io.github.toolfactory.jvm.Driver driver = io.github.toolfactory.jvm.Driver.Factory.getNewNative();
Each functionality offered by the driver is initialized in deferred way at the first call if the driver is not obtained through the method io.github.toolfactory.jvm.Driver.getNew()
. However, it is possible to initialize all of the functionalities at once by calling the method Driver.init()
.
The methods exposed by the Driver interface are the following:
public <D extends Driver> D init();
public <T> T allocateInstance(Class<?> cls);
// Return a ClassLoaderDelegate or the input itself if the input is a
// BuiltinClassLoader or null if the JVM version is less than 9
public ClassLoader convertToBuiltinClassLoader(ClassLoader classLoader);
public Class<?> defineHookClass(Class<?> clientClass, byte[] byteCode);
public Class<?> getBuiltinClassLoaderClass();
public Class<?> getClassLoaderDelegateClass();
public Class<?> getClassByName(String className, Boolean initialize, ClassLoader classLoader, Class<?> caller);
public MethodHandles.Lookup getConsulter(Class<?> cls);
public <T> Constructor<T>[] getDeclaredConstructors(Class<T> cls);
public Field[] getDeclaredFields(Class<?> cls);
public Method[] getDeclaredMethods(Class<?> cls);
public <T> T getFieldValue(Object target, Field field);
public Package getPackage(ClassLoader classLoader, String packageName);
public Collection<URL> getResources(String resourceRelativePath, boolean findFirst, ClassLoader... classLoaders);
public Collection<URL> getResources(String resourceRelativePath, boolean findFirst, Collection<ClassLoader> classLoaders);
public <T> T invoke(Object target, Method method, Object[] params);
public boolean isBuiltinClassLoader(ClassLoader classLoader);
public boolean isClassLoaderDelegate(ClassLoader classLoader);
public <T> T newInstance(Constructor<T> ctor, Object[] params);
public CleanableSupplier<Collection<Class<?>>> getLoadedClassesRetriever(ClassLoader classLoader);
public Map<String, ?> retrieveLoadedPackages(ClassLoader classLoader);
public void setAccessible(AccessibleObject object, boolean flag);
public void setFieldValue(Object target, Field field, Object value);
public void stop(Thread thread);
public <T> T throwException(String message, Object... placeHolderReplacements);
public <T> T throwException(Throwable exception);
In the test folder is also present a little utility class named io.github.toolfactory.util.Reflection
that can be copied into your project and that can be instantiated through the factory methods exposed by the inner static class io.github.toolfactory.util.Reflection.Factory
:
public static Reflection getNew();
public static Reflection getNewWithDefaultDriver();
public static Reflection getNewWithDynamicDriver();
public static Reflection getNewWithHybridDriver();
public static Reflection getNewWithNativeDriver();
public static Reflection getNewWith(Driver driver);
The methods exposed by the io.github.toolfactory.util.Reflection
component are the following:
public Driver getDriver();
public Collection<Method> getDeclaredMethods(Class<?> cls);
public Collection<Method> getAllMethods(Class<?> cls);
public <T> T getFieldValue(Object target, Field field);
public void setFieldValue(Object target, Field field, Object value);
public Field getDeclaredField(Class<?> cls, String name);
public Collection<Field> getDeclaredFields(Class<?> cls);
public Collection<Field> getAllFields(Class<?> cls);
public Collection<Constructor<?>> getDeclaredConstructors(Class<?> cls);
public Collection<Constructor<?>> getAllConstructors(Class<?> cls);
A JDK version 9 or higher is required to compile the project.
For assistance you can: