Nano Hash - криптовалюты, майнинг, программирование

JavaFX 11 javafx.scene.image, созданный из URL-адреса, выдает исключение SSLHandshakeException, когда приложение запускается из встроенного модуля JRT

Я разрабатываю приложение javaFX 11, которое использует класс javafx.scene.image для загрузки изображения с URL:

Image​(String url, boolean backgroundLoading)

где backgroundLoading имеет значение true.

Приложение отлично работает при запуске из моей Eclipse IDE (с использованием Maven). Но когда приложение создается как модульное (JRT) приложение, и я запускаю средство запуска для тестирования сборки, мои объекты Image не загружаются с назначенных им URL-адресов (протокол https) и вместо этого указывают на ошибку. Возвращенное исключение:

java.util.concurrent.ExecutionException: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

Я пробовал переключить backgroundLoading на false и пробовал использовать URL-адреса с других сайтов, которые предоставляют доступ к изображениям. Я даже попытался изменить свойство протокола URL-адресов с «https» на «http». Все тот же результат.

У меня есть класс ImageHandler для обработки создания и настройки объектов javafx.scene.image и другой класс, который использует ImageHandler для установки изображения объекта javafx.scene.image.ImageView (с помощью прослушивателя для проверки завершения фоновой загрузки).

Я не могу предоставить полный код для воспроизведения проблемы, но вот несколько фрагментов из вышеупомянутых классов:

ImageHandler - getImage ():

public Image getImage() {
    if (this.image == null || this.imageHadErrorLoading()) {
        this.imageUrl = String.format(Settings.GATHERER_URL + ImageHandler.QUERY_DATA, this.multiverseId);
        LoggerUtil.logger(this).log(Level.INFO, String.format("URL for image: %s", this.imageUrl));
        try {
            this.image = new Image(this.imageUrl, this.backgroundLoading);
            this.setImageError(false);  
        } catch (Exception e) {
            LoggerUtil.logger(this).log(Level.SEVERE, String.format("Exception creating new Image: %s", e.toString()));
        }
    }

    return this.image;
}

ViewController - setCurrentImage ():

private void setCurrentImage(int multiverseId) {
    ImageHandler imageHandler;
    imageHandler = new ImageHandler(multiverseId, true);
    Image cardImage = imageHandler.getImage();

    // If the image was previously loaded (successfully), just set the image.
    // Otherwise, use a listener to monitor the loading of the image which
    // eventually sets the image once it has successfully loaded.
    if (imageHandler.imageHasLoaded()) {
        this.cardImageView.setImage(cardImage);
        LoggerUtil.logger(this).log(Level.INFO, String.format("Multiverse ID %d: Image cached....getting image....", multiverseId));
    } else {
        // This listener on the image's progress is used to set the Image View when the image has finally loaded. In the meantime,
        // the Image View will continue to display the "placeholder" image.
        cardImage.progressProperty().addListener(new ChangeListener<Number>() {
            @Override
            public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
                double cardProgress = (double) newValue;
                if (cardProgress == 1.0) {
                    if (cardImage.isError()) {
                        cardImageView.setImage(imageHandler.getErrorImage());
                        LoggerUtil.logger(this).log(Level.SEVERE, String.format("Multiverse ID %d: Error loading image.", multiverseId));
                        LoggerUtil.logger(this).log(Level.SEVERE, String.format("Image exception was: %s", cardImage.getException().getMessage()));
                        LoggerUtil.logger(this).log(Level.SEVERE, String.format("Image exception was: %s", cardImage.getException()));
                    } else {
                        cardImageView.setImage(cardImage);
                        imageHandler.setImageLoaded(true);
                        LoggerUtil.logger(this).log(Level.INFO, String.format("Multiverse ID %d: Image loaded successfully! Image URL: %s", multiverseId, cardImage.getUrl()));
                    }
                }
            }
        });
    }

Ожидаемый результат: приложение отображает изображения при запуске из встроенного модуля JRT и ведет себя так же, как при запуске из Eclipse IDE.

Фактический результат: образы приложений создают SSLHandshakeException при запуске из встроенного модуля JRT.


  • Какие модули включены в вашу сгенерированную среду выполнения? 04.09.2019
  • Привет, @swpalmer. Включены следующие модули: - javafx.controls - javafx.fxml - javafx.graphics - javafx.base - java.logging - javafx.web - com.fasterxml.jackson.core - com.fasterxml.jackson.databind - com.fasterxml .jackson.annotation - json.simple (NB: мне пришлось изменить jar-файлы Fastxml и json.simple (загруженные Maven), чтобы превратить их в модульные jar-файлы.) 04.09.2019
  • Я не могу, исходя из вашего описания, воспроизвести проблему с OpenJDK 11.0.2 / OpenJFX 11.0.2 или OpenJDK 12.0.2 / OpenJFX 12.0.2 в Windows 10. Пожалуйста, создайте и предоставьте минимальный воспроизводимый пример, демонстрирующий проблему. Возможно, было бы полезно указать URL-адреса изображений, которые вы пытаетесь отобразить. 04.09.2019
  • @Slaw Это, вероятно, следующий шаг, чтобы предоставить воспроизводимый пример. Сначала я надеялся, что кто-то сможет распознать симптомы, потому что это случилось с ними! Что касается URL-адресов, я пробовал разные сайты, которые дали одинаковый результат. 04.09.2019
  • Попробуйте выполнить поиск в Google на handshake_failure, возможно, некоторая информация, которую вы получите, может помочь вам решить вашу проблему. Возможно, что сервер, с которым вы общаетесь, настроен на автоматическое перенаправление только для обслуживания https, что может быть причиной того, что вы все еще получаете исключения ssl при использовании http. Наборы шифрования SSL, протоколы и цепочка сертификатов на сервере могут не соответствовать тому, что ваш клиент Java настроен для понимания. Вы должны предоставить фактический URL-адрес сервера, обслуживающего изображение, чтобы кто-нибудь, помогающий, мог его протестировать. 04.09.2019
  • Создайте простую одно- или двухстрочную программу и посмотрите, можете ли вы прочитать входной поток по URL-адресу (независимо от JavaFX и всего остального), затем устраните неполадки оттуда. Имейте в виду, что сорняки очень высоки для такого рода вещей, поэтому, если вы углубитесь в них, приготовьтесь заблудиться ;-) 04.09.2019
  • Спасибо за идеи, @jewelsea. Я займусь этим. Полагаю, меня все еще озадачивает, почему мое приложение работает с URL-адресами изображений при запуске из моей Eclipse IDE, но не работает при запуске из созданного образа JRT! 04.09.2019
  • Вероятно, в созданном образе JRT отсутствуют необходимые криптографические библиотеки, сертификаты проверки центра сертификации или параметры крипто-политики, либо сервер настроен неправильно. На данный момент никто не может вам помочь с этим, поскольку в вашем вопросе нет информации о том, как вы создали образ JRT и к какой службе вы пытаетесь подключиться, поэтому никто не может создать тот же образ и подключиться к той же службе, чтобы попробовать отладить его. То, что вы используете JavaFX, изображения, фоновую загрузку и т. Д., Не имеет отношения к вашей проблеме. 05.09.2019
  • Возможно, это дубликат: SSLHandshakeException со средой выполнения, созданной jlink или Получено фатальное предупреждение: handshake_failure в связанной JRE 05.09.2019
  • Спасибо за ссылки @jewelsea. Это место! Проблема заключалась в том, что моему скомпилированному образу JRT требовался jdk.crypto.ec в качестве опции модуля. Он используется JDK при запуске приложения из Eclipse, поэтому он работал в этом случае, но должен быть специально добавлен в качестве опции модуля при создании образа JRT. 05.09.2019
  • Позвольте нам продолжить это обсуждение в чате. 05.09.2019

Ответы:


1

Благодаря @jewelsea я узнал, что мне нужно добавить jdk.crypto.ec в качестве опции модуля при создании приложения с использованием javafx-maven-plugin. Подробности см. В этом ответе.

Он работал нормально при использовании OpenJDK 11 в Eclipse и запуске из исходного кода, но некоторые модули, такие как jdk.crypto.ec, должны быть опущены по умолчанию при создании образа JRT через jlink, если специально не добавлены.

Вот мое обновленное определение javafx-maven-plugin в моем Maven POM:

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <version>0.0.2</version>
    <configuration>
        <release>11</release>
        <jlinkImageName>thecollector</jlinkImageName>
        <launcher>launcher</launcher>
        <mainClass>thecollector/com.cladge.thecollector.MainApp</mainClass>
        <options>
            <option>--add-modules</option>
            <option>jdk.crypto.ec</option>
        </options>
    </configuration>
</plugin>
04.09.2019
  • Я предполагаю, что причина, по которой он был опущен, заключается в том, что это не явная зависимость модулей, с которыми вы напрямую связаны. Шифровальный материал использует механизм поставщика услуг, поэтому провайдеры криптографии могут быть обнаружены во время выполнения, а не быть явно связаны. 06.09.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..