简体   繁体   English

按类名从类路径中的jar中提取类文件

[英]Extracting class file from jar in classpath by classname

I want to extract a class file from jar (if it's in jar) and save it in destination folder. 我想从jar中提取一个类文件(如果在jar中)并将其保存在目标文件夹中。

This what I have now: 这就是我现在所拥有的:

Class Myclass = Thread.currentThread().getContextClassLoader().loadClass(className);
String pathJar = classs.getProtectionDomain().getCodeSource().getLocation().getPath();

pathJar holds the path to the jar with the class. pathJar保存具有该类的jar的路径。

Now, how can i extract the class from there? 现在,我如何从那里提取课程?

The following code, which is live, parses through an ivy dependencies report XML file and extracts all files from the jars within, I hope you find it helpful: 以下是实时代码,它通过一个常春藤依赖项报告XML文件进行解析,并从其中的jar中提取所有文件,希望对您有所帮助:

 private void extract(String path2, String outPath) {
                JarFile zf = null;
                try {
                        zf = new JarFile(path2);
                } catch (IOException e4) {
                        // according to http://stackoverflow.com/a/470492/783412, set the
                        // logger to log these events
                        System.setProperty("java.util.logging.ConsoleHandler.level",
                                        "FINER");
                        logger.throwing(
                                        Thread.currentThread().getStackTrace()[1].getClassName(),
                                        Thread.currentThread().getStackTrace()[1].getMethodName(),
                                        e4);

                        // according to
                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                        // the default logging level is INFO
                        System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");
                } 
                if (zf == null) {
                        System.err.println(path2 + " is an invalid jar, skipping");
                        return;
                }
                Enumeration<JarEntry> ze = (Enumeration<JarEntry>) zf.entries();
                while (ze.hasMoreElements()) {
                        JarEntry thisEntry = ze.nextElement();
                        System.err.println(thisEntry.getName());
                        if (thisEntry.isDirectory()) {
                                new File(outPath + File.separator + thisEntry.getName())
                                                .mkdirs();
                        } else {
                                String filename = thisEntry.getName();
                                if (filename.endsWith("RSA") || filename.endsWith("DSA") || filename.endsWith("SF")) continue;
                                FileOutputStream fos = null;
                                try {
                                        fos = new FileOutputStream(outPath + File.separator
                                                        + filename);
                                } catch (FileNotFoundException e3) {
                                        // according to http://stackoverflow.com/a/470492/783412,
                                        // set the logger to log these events
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1]
                                                        .getClassName(), Thread.currentThread()
                                                        .getStackTrace()[1].getMethodName(), e3);

                                        // according to
                                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                                        // the default logging level is INFO
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "INFO");
                                }
                                BufferedInputStream zis = null;
                                try {
                                        zis = new BufferedInputStream(zf.getInputStream(thisEntry));
                                } catch (IOException e2) {
                                        // according to http://stackoverflow.com/a/470492/783412,
                                        // set the logger to log these events
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1]
                                                        .getClassName(), Thread.currentThread()
                                                        .getStackTrace()[1].getMethodName(), e2);

                                        // according to
                                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                                        // the default logging level is INFO
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "INFO");
                                }
                                try {
                                        fos = new FileOutputStream(outPath + File.separator
                                                        + thisEntry.getName());
                                } catch (FileNotFoundException e1) {
                                        // according to http://stackoverflow.com/a/470492/783412,
                                        // set the logger to log these events
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1]
                                                        .getClassName(), Thread.currentThread()
                                                        .getStackTrace()[1].getMethodName(), e1);

                                        // according to
                                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                                        // the default logging level is INFO
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "INFO");
                                }
                                byte[] b = new byte[new Long(thisEntry.getSize()).intValue()];
                                try {
                                        zis.read(b);
                                } catch (IOException e1) {
                                        // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events
                                        System.setProperty("java.util.logging.ConsoleHandler.level","FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1);

                                        // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO
                                        System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");           
                                }
                                try {
                                                        .getClassName(), Thread.currentThread()
                                                        .getStackTrace()[1].getMethodName(), e1);

                                        // according to
                                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                                        // the default logging level is INFO
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "INFO");
                                }
                                byte[] b = new byte[new Long(thisEntry.getSize()).intValue()];
                                try {
                                        zis.read(b);
                                } catch (IOException e1) {
                                        // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events
                                        System.setProperty("java.util.logging.ConsoleHandler.level","FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1);

                                        // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO
                                        System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");           
                                }
                                try {
                                        fos.write(b);
                                } catch (IOException e1) {
                                        // according to http://stackoverflow.com/a/470492/783412, set the logger to log these events
                                        System.setProperty("java.util.logging.ConsoleHandler.level","FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1].getClassName(), Thread.currentThread().getStackTrace()[1].getMethodName(), e1);
                                        // according to http://stackoverflow.com/questions/4970513/java-logging-levels-confusion, the default logging level is INFO
                                        System.setProperty("java.util.logging.ConsoleHandler.level", "INFO");           
                                } 
                                try {
                                        fos.close();
                                } catch (IOException e) {
                                        // according to http://stackoverflow.com/a/470492/783412,
                                        // set the logger to log these events
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "FINER");
                                        logger.throwing(Thread.currentThread().getStackTrace()[1]
                                                        .getClassName(), Thread.currentThread()
                                                        .getStackTrace()[1].getMethodName(), e);

                                        // according to
                                        // http://stackoverflow.com/questions/4970513/java-logging-levels-confusion,
                                        // the default logging level is INFO
                                        System.setProperty(
                                                        "java.util.logging.ConsoleHandler.level", "INFO");
                                }
                        }
                }
        }

Check if you can leverage ASM for your requirement. 检查是否可以利用ASM满足您的要求。 There are couple of other options as well like BCEL . 还有其他几种选择,例如BCEL

You should be able to extract your class directly from memory with all of its inner classes when it is available on your classpath. 当类路径中有可用的所有内部类时,您应该能够直接从内存中提取您的类。 Inner classes will be separated with $, at least on Oracle 1.8 JVM. 至少在Oracle 1.8 JVM上,内部类将用$分隔。

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class ExtractClass {
    public static void main(String... args) throws ClassNotFoundException, IOException {
        final String name = args[0];

        extractClass(name, Paths.get(name));
    }

    private static void extractClass(final String name, final Path path) throws IOException, ClassNotFoundException {
        final Class<?> clazz = Class.forName(name);

        try (InputStream inputStream = Object.class.getResourceAsStream("/" + name.replace(".", "/") + ".class")) {
            Files.copy(inputStream, Paths.get(name));
        }

        // Retrieve all inner classes
        for (final Class<?> innerClass : clazz.getDeclaredClasses()) {
            extractClass(innerClass.getName(), Paths.get(innerClass.getName()));
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM