У меня есть два файла jar (в качестве примера можно назвать их Updater.jar и Code.jar). Updater.jar запускается с его основным методом, а затем снова запускает себя с помощью метода premain:Добавление файла jar к пути к инструментарию
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, но для использования этого мне нужно будет получить List> всех классов в банке, которые я не смог выполнить.
Допустим, что Code.jar имеет три файла класса: Main.class, writer.class и display.class. Есть ли способ получить список каждого из объектов класса, а не их имя?
Просто добавьте требуемую банку в путь класса. – ManoDestra
Это только изменение переменной java.library.path? – JD9999
Я имел в виду просто добавив требуемую банку к пути к классам, например. java -cp path/to/your.jar; path/to/other.jar com.example.app.MainApp. Не уверен, что это то, что вы имели в виду? Кроме того, вы можете добавлять JAR динамически во время выполнения через класс URLClassLoader, если вы ищете большую гибкость. – ManoDestra