简体   繁体   English

从以字节数组表示的jar文件中加载类的问题

[英]Issue with loading class from jar file represented as byte array

I'm trying to create an instance of a class from jar file loaded on a byte array. 我正在尝试从加载在字节数组上的jar文件创建类的实例。

I'm receiving two args: 我收到两个参数:
1. byte[] which represents jar file with required class 1. byte []代表具有所需类的jar文件
2. Qualified class name 2.合格的班级名称

When I'm testing it locally it works as expected, but when I upload exactly the same jar file with the same qualified class name remotely (using web application implemented with Spring MVC for back and AngularJS for front end deployed in Tomcat server) It can't find the required class: 当我在本地对其进行测试时,它可以按预期工作,但是当我远程上载具有相同合格类名的完全相同的jar文件时(使用在Tomcat服务器中部署的Spring MVC实现的Web应用程序(用于后端)和AngularJS实现的前端)找不到所需的课程:

java.lang.ClassNotFoundException 抛出java.lang.ClassNotFoundException

When I was debugging, it turned out, that classloader is properly invoked but no one class is loaded from jar. 事实证明,当我进行调试时,该类加载器已正确调用,但没有从jar加载任何类。

I would be grateful if anyone can tell what can be the reason of that difference or how can I implement this functionality in other ways. 如果有人能说出造成这种差异的原因是什么,或者我如何以其他方式实现此功能,我将不胜感激。


A method which loads class and returns an instance of it: 一种加载类并返回其实例的方法:

public static <T> T getInstanceOfLoadedClass(byte[] jarFileBytes, String qualifiedClassName) throws ClassFromJarInstantiationException {
    LOGGER.info("Getting instance of class from loaded jar file. Class name: " + qualifiedClassName);
    try {
        return (T) Class.forName(qualifiedClassName, true, new ByteClassLoader(jarFileBytes)).newInstance();
    } catch (InstantiationException | IllegalAccessException | IOException | ClassNotFoundException | NoSuchFieldException e) {
        LOGGER.error("Exception was thrown while reading jar file for " + qualifiedClassName + "class.", e);
        throw new ClassFromJarInstantiationException(e);
    }
}

Custom ByteClassLoader: 自定义ByteClassLoader:

public class ByteClassLoader extends ClassLoader {
    private static final Logger LOGGER = Logger.getLogger(ByteClassLoader.class);
    private final byte[] jarBytes;
    private final Set<String> names;

    public ByteClassLoader(byte[] jarBytes) throws IOException {
        this.jarBytes = jarBytes;
        this.names = loadNames(jarBytes);
    }

    private Set<String> loadNames(byte[] jarBytes) throws IOException {
        Set<String> set = new HashSet<>();
        try (ZipInputStream jis = new ZipInputStream(new ByteArrayInputStream(jarBytes))) {
            ZipEntry entry;
            while ((entry = jis.getNextEntry()) != null) {
                set.add(entry.getName());
            }
        }
        return Collections.unmodifiableSet(set);
    }

    @Override
    public InputStream getResourceAsStream(String resourceName) {
        if (!names.contains(resourceName)) {
            return null;
        }
        boolean found = false;
        ZipInputStream zipInputStream = null;
        try {
            zipInputStream = new ZipInputStream(new ByteArrayInputStream(jarBytes));
            ZipEntry entry;
            while ((entry = zipInputStream.getNextEntry()) != null) {
                if (entry.getName().equals(resourceName)) {
                    found = true;
                    return zipInputStream;
                }
            }
        } catch (IOException e) {
            LOGGER.error("ByteClassLoader threw exception while reading jar byte stream for resource: "+resourceName, e);
            e.printStackTrace();
        } finally {
            if (zipInputStream != null && !found) {
                try {
                    zipInputStream.close();
                } catch (IOException e) {
                    LOGGER.error("ByteClassLoader threw exception while closing jar byte stream for resource: "+resourceName, e);
                    e.printStackTrace();
                }
            }
        }
        return null;
    } }

The problem was that the class required to be loaded was in a range of classloader while it was tested. 问题在于,在测试该类时,需要加载的类在一个类加载器中。
Hope it helps someone in solving this problem because it is really easy to miss. 希望它可以帮助某人解决此问题,因为它很容易遗漏。

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

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