我正在寻找黑客来在JRE 9+上运行时访问Java工具,而又不会弄乱启动参数等。我实际上没有任何目标,我只是想知道是否仍然可能。
对于Java 8及更低版本的Java,它看起来像这样(在byte-buddy-agent
库的帮助下):
public static void main(String[] args) throws Exception {
// inject tools to class loader
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
addURL.setAccessible(true);
addURL.invoke(systemClassLoader, new File("B:/Java/tools/j8/tools-min.jar").toURI().toURL());
// append folder with attach(.dll) library in it
System.setProperty("java.library.path", System.getProperty("java.library.path") + ';' + "B:/Java/tools/j8");
// force reset sys_paths to allow for recreation on next library load
Field sys_paths = ClassLoader.class.getDeclaredField("sys_paths");
sys_paths.setAccessible(true);
sys_paths.set(null, null);
// load attach(.dll)
System.loadLibrary("attach");
// now byte buddy can do everything for you
Instrumentation instrumentation = ByteBuddyAgent.install();
System.out.println(instrumentation); // works!
}
tools.jar
是从JDK到jdk8/lib/tools.jar
的正确系统的路径-您也不需要所有类,因此最终的.jar可能只有几kb(在Windows上为35kB),而不是大约如果是Windows,则为17MB。您还可以从多个系统中提取和合并类,以创建单个tools.jar
,该类适用于每个系统。
上面的方法也适用于linux(如果您提供有效的tools.jar
和attach.so
库),但是似乎在Linux上的许多jre发行版中都已经存在attach库,因此可以改用以下代码:
public static void linux() {
Instrumentation instrumentation = ByteBuddyAgent.install(() -> {
File toolsJar = new File("B:/Java/tools/j8/tools-min.jar");
try {
if (toolsJar.isFile() && toolsJar.canRead()) {
return Accessor.Simple.of(new URLClassLoader(new URL[]{toolsJar.toURI().toURL()}, null));
}
return Accessor.Unavailable.INSTANCE;
} catch (MalformedURLException e) { throw new RuntimeException(e); }
});
System.out.println(instrumentation); // works!
}
JRE 9+中的模块和新的系统类加载器发生了很大变化,我只知道我需要以某种方式将JDK的attach.jmod加载到JRE。
但是到目前为止,我还没有找到解决方法,我想知道是否仍然有可能。
另外,在JRE 9上还需要其他一些技巧来禁用自我附加保护,但这也很简单,我只是找不到一种使附加提供者实际返回有效值的方法,因为服务也从Java 9更改了。