I'm trying to insert my custom class to Bootstrap Classloader to be able to call sun.nio.ch.IOUtil#fdVal(FileDescriptor) to get the value of the FileDescriptor and use it in my Advice (I wrapped sun.nio.ch.FileChannelImpl)
I successfully inserted my pbouda.agents.core.Utils into the bootstrap classloader.
public abstract class Utils {
public static final int ERROR_FD_VALUE = Integer.MIN_VALUE;
private static Method FD_VALUE_METHOD;
static {
try {
Class<?> clazz = Class.forName("sun.nio.ch.IOUtil");
FD_VALUE_METHOD = clazz.getMethod("fdVal", FileDescriptor.class);
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
}
}
public static int fdVal(FileDescriptor fd) {
if (FD_VALUE_METHOD != null) {
try {
return (int) FD_VALUE_METHOD.invoke(null, fd);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
return ERROR_FD_VALUE;
}
}
using
public abstract class UtilsInitializer {
private static boolean INITIALIZED = false;
public static synchronized void initialize() {
if (!INITIALIZED) {
TypePool typePool = TypePool.Default.ofSystemLoader();
Map<TypeDescription, byte[]> types = new ByteBuddy()
.redefine(
typePool.describe("pbouda.agents.core.Utils").resolve(),
ClassFileLocator.ForClassLoader.ofSystemLoader())
.make()
.getAllTypes();
ClassInjector.UsingUnsafe.ofBootLoader()
.inject(types);
INITIALIZED = true;
}
}
}
I've proved it!
~ jcmd 281091 VM.classloaders show-classes [21/09/21|11:50AM]
281091:
+-- <bootstrap>
|
| Classes: java.lang.Object
| [Ljava.lang.Object;
| [[Ljava.lang.Object;
| java.io.Serializable
...
| pbouda.agents.core.Utils
| (1522 classes)
|
| Hidden Classes: java.lang.invoke.LambdaForm$DMH/0x0000000800d89c00
| java.lang.invoke.LambdaForm$DMH/0x0000000800d89800
Unfortunately, it's in a different module of course :(
java.lang.IllegalAccessException: class pbouda.agents.core.Utils cannot access class sun.nio.ch.IOUtil
(in module java.base) because module java.base does not export sun.nio.ch to unnamed module @7e928e2f
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:392)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:674)
at java.base/java.lang.reflect.Method.invoke(Method.java:560)
at pbouda.agents.core.Utils.fdVal(Utils.java:26)
at java.base/sun.nio.ch.FileChannelImpl.open(FileChannelImpl.java:151)
at java.base/sun.nio.fs.UnixChannelFactory.newFileChannel(UnixChannelFactory.java:134)
at java.base/sun.nio.fs.UnixChannelFactory.newFileChannel(UnixChannelFactory.java:146)
at java.base/sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:217)
at java.base/java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:484)
at java.base/java.nio.file.Files.newOutputStream(Files.java:228)
at java.base/java.nio.file.Files.newBufferedWriter(Files.java:3008)
at java.base/java.nio.file.Files.newBufferedWriter(Files.java:3056)
at pbouda.agents.file.FileTest.bufferedWriter(FileTest.java:38)
Do you know how to inject it into java.base to avoid running the program with add-opens ?