Я работаю над проектом, в котором мы используем библиотеку, которая не гарантируется потокобезопасностью (и не является) и однопоточной в сценарии потоков Java 8, которая работает так, как ожидалось.
Мы хотели бы использовать параллельные потоки, чтобы получить плоды масштабирования с низкой видимостью.
К сожалению, это приводит к сбою библиотеки - скорее всего, потому, что один экземпляр вмешивается в переменные, совместно используемые с другим экземпляром, поэтому нам нужна изоляция.
Я рассматривал возможность использования отдельного загрузчика классов для каждого экземпляра (возможно, локального потока), который, насколько мне известно, должен означать, что для всех практических целей я получаю необходимую изоляцию, но я не знаком с намеренно созданием загрузчиков классов для этой цели.
Это правильный подход? Как мне это сделать, чтобы иметь надлежащее качество продукции?
Изменить: меня попросили получить дополнительную информацию о ситуации, вызвав вопрос, чтобы лучше понять ее. Вопрос по-прежнему связан с общей ситуацией, а не с фиксацией библиотеки.
У меня есть полный контроль над объектом, созданным библиотекой (которая https://github.com/veraPDF/), которую вытащил
<dependency>
<groupId>org.verapdf</groupId>
<artifactId>validation-model</artifactId>
<version>1.1.6</version>
</dependency>
используя репозиторий проекта maven для артефактов.
<repositories>
<repository>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>vera-dev</id>
<name>Vera development</name>
<url>http://artifactory.openpreservation.org/artifactory/vera-dev</url>
</repository>
</repositories>
В настоящее время невозможно закрепить библиотеку.
EDIT: меня попросили показать код. Наш основной адаптер примерно:
public class VeraPDFValidator implements Function<InputStream, byte[]> {
private String flavorId;
private Boolean prettyXml;
public VeraPDFValidator(String flavorId, Boolean prettyXml) {
this.flavorId = flavorId;
this.prettyXml = prettyXml;
VeraGreenfieldFoundryProvider.initialise();
}
@Override
public byte[] apply(InputStream inputStream) {
try {
return apply0(inputStream);
} catch (RuntimeException e) {
throw e;
} catch (ModelParsingException | ValidationException | JAXBException | EncryptedPdfException e) {
throw new RuntimeException("invoking VeraPDF validation", e);
}
}
private byte[] apply0(InputStream inputStream) throws ModelParsingException, ValidationException, JAXBException, EncryptedPdfException {
PDFAFlavour flavour = PDFAFlavour.byFlavourId(flavorId);
PDFAValidator validator = Foundries.defaultInstance().createValidator(flavour, false);
PDFAParser loader = Foundries.defaultInstance().createParser(inputStream, flavour);
ValidationResult result = validator.validate(loader);
// do in-memory generation of XML byte array - as we need to pass it to Fedora we need it to fit in memory anyway.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XmlSerialiser.toXml(result, baos, prettyXml, false);
final byte[] byteArray = baos.toByteArray();
return byteArray;
}
}
которая является функцией, которая отображает из InputStream (предоставляя PDF файл) в массив байтов (представляющий вывод отчета XML).
(Увидев код, я заметил, что есть вызов инициализатора в конструкторе, который может быть виновником здесь в моем конкретном случае. Мне все равно хотелось бы решить общую проблему.