在运行时在JRE 9+上初始化Java工具

时间:2018-07-23 19:57:28

标签: java reflection instrumentation

我正在寻找黑客来在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.jarattach.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更改了。

0 个答案:

没有答案