2017-02-14 2 views
0

Я пытаюсь создать экземпляр класса из файла jar, загруженного в массив байтов.

Я получаю два аргумента:
1. байт [], который представляет собой файл банку с требуемым классом
2. Название Квалифицированный класс

Когда я проверяю его на месте он работает, как ожидалось, но когда я загрузить точно такой же файл jar с таким же именем квалифицированного класса удаленно (с использованием веб-приложения, реализованного с помощью Spring MVC for back и AngularJS для внешнего интерфейса, развернутого на сервере Tomcat). Он не может найти необходимый класс:

java.lang.ClassNotFoundException

Когда я отлаживал, он превратился в ou t, этот класс загрузчик правильно вызывается, но ни один класс не загружается из jar.

Я был бы признателен, если кто-нибудь сможет сказать, что может быть причиной этой разницы или как я могу реализовать эту функциональность другими способами.


Метод, который загружает класс и возвращает его экземпляр:
Проблема с классом загрузки из jar-файла, представленного как массив байтов

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); 
    } 
} 

Выборочная 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; 
    } } 

ответ

0

Проблема заключалась в том, что класс должен быть загружен находился в диапазоне загрузчика классов, когда он был протестирован.
Надеюсь, это поможет кому-то в решении этой проблемы, потому что это действительно легко пропустить.

Смежные вопросы