将 jar 文件添加到检测路径

2024-02-14

我有两个 jar 文件(例如,我们将它们称为 Updater.jar 和 Code.jar)。 Updater.jar 使用其 main 方法启动,然后使用 premain 方法再次启动自身:

package Update;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

public class InstructionLauncher {

    private List<UpdateInstruction> instructions = new ArrayList<UpdateInstruction>();
    private static InstructionLauncher instance;
    private Process process;

    public static InstructionLauncher initialise(){
        if(instance !=null) return instance;
        else return new InstructionLauncher();
    }

    public void registerPremain(UpdateInstruction inst){
        instructions.add(inst);
    }

    public void launchNext(){
        UpdateInstruction inst = instructions.get(0);
        String cls = inst.getClassName() + "." + inst.getMethodName();
        String[] args = new String[]{"java", "-javaagent", "JOSUpdater.jar", "-jar", inst.getClassName() + "." + inst.getMethodName()};
        ProcessBuilder builder = new ProcessBuilder(args);
        try {
            exportResource(cls, cls);
        } catch (Exception e) {
            UpdateManager.revert();
        }
        try {
            Process p = builder.start();
            process = p;
        } catch (IOException e) {
            e.printStackTrace();
        }
        while(!process.isAlive())launchNext();
    }

    private InstructionLauncher(){
        instance = this;
    }

    //From http://stackoverflow.com/questions/10308221/how-to-copy-file-inside-jar-to-outside-the-jar
    private String exportResource(String resourceName, String clazz) throws Exception {
        InputStream stream = null;
        OutputStream resStreamOut = null;
        String jarFolder;
        try {
            stream = Class.forName(clazz).getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
            if(stream == null) {
                throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
            }

            int readBytes;
            byte[] buffer = new byte[4096];
            jarFolder = new File(Class.forName(clazz).getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
            resStreamOut = new FileOutputStream(jarFolder + resourceName);
            while ((readBytes = stream.read(buffer)) > 0) {
                resStreamOut.write(buffer, 0, readBytes);
            }
        } catch (Exception ex) {
            throw ex;
        } finally {
            stream.close();
            resStreamOut.close();
        }

        return jarFolder + resourceName;
    }

}

premain 方法现在看起来像这样:

package Update;

import java.lang.instrument.Instrumentation;

public class PremainLauncher {

    public static void premain(String args, Instrumentation inst){
        inst.addTransformer(new Transformer(), true);
        System.out.println("Registered instruction for package: " + args);
    }

}

我想知道如何将整个外部 JAR(本例中为 Code.jar)添加到仪器的路径中?

我知道 Instrumentation.retransformClasses 方法,但要使用该方法,我需要获取 jar 中所有类的 List> ,但我无法完成该操作。

假设 Code.jar 有三个类文件:Main.class、writer.class 和 display.class。有没有办法获取每个类对象的列表,而不是他们的名字?


Java 代理可以简单地通过以下方式添加 jar 文件Instrumentation https://docs.oracle.com/javase/8/docs/api/?java/lang/instrument/Instrumentation.html它在启动方法中接收到的接口,例如

import java.io.IOException;
import java.lang.instrument.Instrumentation;
import java.util.jar.JarFile;

public class PremainLauncher {
    public static void premain(String args, Instrumentation inst) throws IOException{
        inst.appendToSystemClassLoaderSearch(new JarFile("Code.jar"));
        inst.addTransformer(new Transformer(), true);
        System.out.println("Registered instruction for package: " + args);
    }
}

See Instrumentation.appendToSystemClassLoaderSearch(…) https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#appendToSystemClassLoaderSearch-java.util.jar.JarFile-。如果您还打算以被检测的类需要访问以下类的方式来检测 JRE 类:Code.jar,你必须更改引导路径 https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#appendToBootstrapClassLoaderSearch-java.util.jar.JarFile-反而。

请注意,这必须尽早发生:

Java™ 虚拟机规范指定后续尝试解析 Java 虚拟机之前未成功尝试解析的符号引用始终会失败,并出现与初始解析尝试所引发的相同错误。因此,如果 JAR 文件包含与 Java 虚拟机尝试解析引用失败的类相对应的条目,则解析该引用的后续尝试将失败,并出现与初始尝试相同的错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 jar 文件添加到检测路径 的相关文章

  • 如何使用 Apache POI API 将图像添加到 pptx 中添加的图像占位符?

    我已经预定义了带有文本和图像占位符的 pptx 模板 我如何从模板访问和修改这些占位符 我可以使用 POI pptx API 直接将图像和文本添加到幻灯片中 但如何将其添加到模板的占位符中 请参阅链接以了解如何添加占位符来创建固定模板 ht
  • Java - 为什么不允许 Enum 作为注释成员?

    It says 原始 String Class an Enum 另一个注释 上述任何一个的数组 只有这些类型才是合法的 Annotation 成员 为什么泛型 Enum 不能成为 Annotation 的成员 例如 Retention Re
  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • 使用 JPA Criteria API 进行分页的总行数

    我正在系统中为实体实现 高级搜索 功能 以便用户可以使用该实体的属性上的多个条件 eq ne gt lt 等 来搜索该实体 我正在使用 JPA 的 Criteria API 动态生成 Criteria 查询 然后使用setFirstResu
  • 如何使用 Java 处理 Selenium WebDriver 中的新窗口?

    这是我的代码 driver findElement By id ImageButton5 click Thread sleep 3000 String winHandleBefore driver getWindowHandle drive
  • 比较两个文本文件的最快方法是什么,不将移动的行视为不同

    我有两个文件非常大 每个文件有 50000 行 我需要比较这两个文件并识别更改 然而 问题是如果一条线出现在不同的位置 它不应该显示为不同的 例如 考虑这个文件A txt xxxxx yyyyy zzzzz 文件B txt zzzzz xx
  • java中如何连接字符串

    这是我的字符串连接代码 StringSecret java public class StringSecret public static void main String args String s new String abc s co
  • 当从服务类中调用时,Spring @Transactional 不适用于带注释的方法

    在下面的代码中 当方法内部 是从内部调用的方法外部 应该在交易范围内 但事实并非如此 但当方法内部 直接从调用我的控制器class 它受到事务的约束 有什么解释吗 这是控制器类 Controller public class MyContr
  • 如何安全地解决这个 Java 上下文类加载器问题?

    我的数百名用户中只有一位在启动我的 Java 桌面应用程序时遇到问题 他只有大约三分之一的时间开始 另外三分之二的时间在启动时抛出 NullPointerException Exception in thread AWT EventQueu
  • 如何模拟从抽象类继承的受保护子类方法?

    如何使用 Mockito 或 PowerMock 模拟由子类实现但从抽象超类继承的受保护方法 换句话说 我想在模拟 doSomethingElse 的同时测试 doSomething 方法 抽象超类 public abstract clas
  • 在 S3 中迭代对象时出现“ConnectionPoolTimeoutException”

    我已经使用 aws java API 一段时间了 没有遇到太多问题 目前我使用的是库 1 5 2 版本 当我使用以下代码迭代文件夹内的对象时 AmazonS3 s3 new AmazonS3Client new PropertiesCred
  • 画透明圆,外面填充

    我有一个地图视图 我想在其上画一个圆圈以聚焦于给定区域 但我希望圆圈倒转 也就是说 圆的内部不是被填充 而是透明的 其他所有部分都被填充 请参阅这张图片了解我的意思 http i imgur com zxIMZ png 上半部分显示了我可以
  • hibernate锁等待超时超时;

    我正在使用 Hibernate 尝试模拟对数据库中同一行的 2 个并发更新 编辑 我将 em1 getTransaction commit 移至 em1 flush 之后我没有收到任何 StaleObjectException 两个事务已成
  • 在 Netbeans 8 上配置 JBoss EAP 的问题

    我已经下载了 JBoss EAP 7 并正在 Netbeans 8 上配置它 我已经到达向导 实例属性 其中要求从选择框中选择 域 当我打开选择框时 它是空的 没有什么可以选择的 因此 完成 按钮也处于非活动状态 这使得无法完成配置 我通过
  • 在游戏视图下添加 admob

    我一直试图将 admob 放在我的游戏视图下 这是我的代码 public class HoodStarGame extends AndroidApplication Override public void onCreate Bundle
  • 在 Spring 中重构这个的最佳方法?

    private final ExecutorService executorParsers Executors newFixedThreadPool 10 public void parse List
  • java.lang.NumberFormatException: Invalid int: "3546504756",这个错误是什么意思?

    我正在创建一个 Android 应用程序 并且正在从文本文件中读取一些坐标 我在用着Integer parseInt xCoordinateStringFromFile 将 X 坐标转换为整数 Y 坐标的转换方法相同 当我运行该应用程序时
  • 测试弱引用

    在 Java 中测试弱引用的正确方法是什么 我最初的想法是执行以下操作 public class WeakReferenceTest public class Target private String value public Targe
  • HQL Hibernate 内连接

    我怎样才能在 Hibernate 中编写这个 SQL 查询 我想使用 Hibernate 来创建查询 而不是创建数据库 SELECT FROM Employee e INNER JOIN Team t ON e Id team t Id t
  • FileOutputStream.close() 中的设备 ioctl 不合适

    我有一些代码可以使用以下命令将一些首选项保存到文件中FileOutputStream 这是我已经写了一千遍的标准代码 FileOutputStream out new FileOutputStream file try BufferedOu

随机推荐