JavaFX и внешние JAR-файлы

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

java.lang.RuntimeException: java.lang.ExceptionInInitializerError

Caused by: java.lang.ExceptionInInitializerError
at common.bo.property.TextAttributeProp.checkLimit(TextAttributeProp.java:125)

У меня есть common.jar в моей папке lib и пути к классам. Я также использую неограниченный доступ в свойствах проекта. И я также знаю об этой теме приложение JavaFx 2.0, ссылающееся на внешние банки, но это не сработает для меня. Все работает нормально, когда я запускаю его из Netbeans. Но в браузере он не инициализирует классы во внешних банках. Не могли бы вы мне помочь. Спасибо

файл jnlp здесь

 <?xml version="1.0" encoding="utf-8"?>
    <jnlp spec="1.0" xmlns:jfx="http://javafx.com" href="JavaFXSklad2.jnlp">
    <information>
    <title>JavaFXSklad2</title>
    <vendor>xxx</vendor>
    <description>Sample JavaFX 2.0 application.</description>
    <offline-allowed/>
    </information>
    <resources os="Windows">
    <jfx:javafx-runtime version="2.0+" href="http://javadl.sun.com/webapps/download/GetFile/javafx-latest/windows-i586/javafx2.jnlp"/>
    </resources>
  <resources>
     <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
         <jar href="JavaFXSklad2.jar" size="164987" download="eager" />
         <jar href="lib/common.jar" size="965131" download="eager" />
        <jar href="lib/ifxjdbc.jar" size="705534" download="eager" />
        <jar href="lib/infra.jar" size="588915" download="eager" />
    <jar href="lib/jdawt.jar" size="726475" download="eager" />
    <jar href="lib/toplink.jar" size="1450414" download="eager" />
    <jar href="lib/weblogic.jar" size="55582010" download="eager" />
      </resources>
    <security>
      <all-permissions/>
    </security>
      <applet-desc  width="800" height="600" main-class="com.javafx.main.NoJavaFXFallback"  name="JavaFXSklad2" />
  <jfx:javafx-desc  width="800" height="600" main-class="md.MainMenu"  name="JavaFXSklad2" />
  <update check="background"/> 
    </jnlp>

Изменить> Наконец я понимаю, что проблема вызвана статическим блоком в классе в банке в этой строке>

String osName= (String) System.getProperties().get("os.name");

Я также пытаюсь подписать внешние банки и банку javafx одним и тем же сертификатом, но безуспешно.


person troger19    schedule 31.01.2012    source источник
comment
Не могли бы вы добавить .jnlp файл, созданный NetBeans для вашего проекта JavaFX.   -  person Sergey Grinev    schedule 31.01.2012


Ответы (4)


Если вы используете NetBeans 7.1, вам необходимо обновить NetBeans до последней ночной версии http://bits.netbeans.org/download/trunk/nightly/latest/.

В более ранних версиях NetBeans обнаружена ошибка при упаковке jar-файлов http://netbeans.org/bugzilla/show_bug.cgi?id=205844.

Вы можете увидеть, есть ли эта ошибка в сгенерированном пакете NetBeans, распаковав jar-файлы вашего приложения и проверив, что его файл META-INF/MANIFEST.MF содержит ссылки на ваши внешние jar-файлы.

Похоже, что используемые вами jar-файлы (например, Toplink, jdbc и WebLogic) требуют привилегий безопасности выше тех, которые доступны для неподписанного приложения, поэтому вам также необходимо запросить дополнительные разрешения безопасности, как рекомендует Сергей, и подписать свое приложение. Сделать это:

  1. Щелкните правой кнопкой мыши свой проект в NetBeans.
  2. Выберите Построить | Развертывание
  3. Проверьте запрос на неограниченный доступ.
  4. Если у вас есть сертификат подписи от ЦС, нажмите кнопку Изменить... рядом с сертификатом подписи, в противном случае просто примите самозаверяющий сертификат, созданный NetBeans по умолчанию.

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


В Java при сбое статической инициализации класса загрузка класса не будет завершена, даже если класс доступен и находится в пути к классу. Это означает, что первая ссылка на класс будет генерировать ExceptionInInitializerError, а последующие ссылки на класс будут генерировать, что часто вводит в заблуждение, ClassNotFoundException.

ExceptionInInitializerError выдается, чтобы указать, что во время оценки статического инициализатора или инициализатора для статической переменной произошло исключение. Jar, содержащий файл класса, вызывающий ошибку, был найден, и загрузка класса началась, но не может быть завершена, поскольку в его статических переменных или конструкторе возникли ошибки.

Подозрительный код будет TextAttributeProp.checkLimit(TextAttributeProp.java:125), хотя основная причина вашей проблемы может быть в другом месте. Проверьте, что делает статический код TextAttributeProp, и оберните статические методы инициализации в блоки try catch, чтобы получить дополнительную отладочную информацию, выполнить резервное действие или игнорировать статическую ошибку инициализации.


System.getProperties() не вернет вам нужные свойства в неподписанном апплете — он просто вернет null. Затем вы пытаетесь разыменовать это нулевое значение в статическом инициализаторе, который генерирует NullPointerException и приводит к сбою загрузки вашего класса, а последующие ссылки на класс вызывают ClassNotFoundException.

Если вы напрямую получаете свойство "os.name" через System.getProperty("os.name"), а не получаете все системные свойства, это работает, потому что "os.name" не помечено как чувствительное к безопасности. Чтобы узнать, какие свойства можно и нельзя запрашивать у апплета, см.: http://docs.oracle.com/javase/tutorial/deployment/doingMoreWithRIA/properties.html. Также обратите внимание, что неподписанный апплет не может устанавливать какие-либо системные свойства.


Если ваше приложение правильно подписано, вы сможете получить и установить любые свойства системы, которые вы хотите. Если вы не можете этого сделать, вы можете сообщить об ошибке в подключаемом модуле браузера JavaFX по адресу http://javafx-jira.kenai.com. Сначала убедитесь, что вы правильно подписали свое приложение, попытавшись сделать что-то еще, что требует повышенных привилегий, например, прочитать файл из вашей корневой файловой системы из подписанного апплета и убедиться, что чтение не завершается ошибкой.

person jewelsea    schedule 01.02.2012
comment
Привет. Я устанавливаю новую версию Netbeans по вашей ссылке, но безуспешно. Проблема остается. В манифесте у меня есть ссылки на мои банки, и я также подписываю свое приложение раньше, потому что без подписи я не мог даже заполнять таблицы из данных базы данных. Вот файл манифеста> Версия манифеста: 1.0 Версия JavaFX: 2.0 Название реализации: JavaFXSklad2 Версия реализации: 1.0 Класс приложения JavaFX: md.MainMenu Путь класса JavaFX: lib/common.jar lib/ifxjdbc.jar lib/infra.jar lib/jd awt.jar lib/toplink.jar lib/weblogic.jar Разработчик: JavaFX Packager - person troger19; 01.02.2012
comment
Обновлен ответ, чтобы включить информацию о статических ошибках инициализации и о том, как они могут относиться к ClassNotFoundException. - person jewelsea; 03.02.2012
comment
Я думаю, проблема в том, что я не могу получить доступ к системным свойствам из браузера. Этот код находится в статическом блоке в банке 'String osName= (String) System.getProperties().get(os.name);' и поскольку osName имеет значение NULL, конструктор терпит неудачу. Решение может заключаться в том, чтобы подписать jar-файлы, я думаю, что подписал его правильно, но все еще нулевой указатель на System.getProperties и сбой. - person troger19; 06.02.2012

Извините, ребята, я немного ввел вас в заблуждение. Проблема, почему мое приложение работает под Netbeans, а в браузере не было этой строки в статическом блоке в моей банке:

String osName = (String) System.getProperties().get("os.name");

которые возвращают правильное значение в Netbeans (Windows Xp), но Null в браузере. Но когда я немного изменяю код на этот >

 String osName = (String) System.getProperty("os.name");

он также возвращает правильное значение в браузере. Так что это не имеет ничего общего с внешними банками или подписью приложения. Проблема все еще остается, потому что внешние банки являются частью нашей корпоративной инфраструктуры Java, поэтому я просто не могу напрямую изменить код, но это будет другая тема :)

person troger19    schedule 06.02.2012

Судя по jnlp, вы не пересоздали jnlp после включения Unrestricted access. Попробуйте запустить Clean and Build или добавить следующий тег в ваш jnlp вручную:

<security>
  <all-permissions/>
</security>
person Sergey Grinev    schedule 31.01.2012

Я сталкивался с подобными ситуациями. Я точно не знаю, какое решение может вам помочь.. поэтому я перечислю их все:

1- убедитесь, что используемая вами банка подписана, а подпись действительна. Вы можете использовать jarsigner для этих целей.. потому что, если срок действия используемых вами банок истек ... приложение выйдет из строя @ web. если есть баночка подписанная и просроченная. просто удалите все файлы из META-INF. (кстати, jar - это zip-файл)

2-я вижу ваш JNLP.. вам нужно добавить этот атрибут для класса приложения: main="true" так что ваш будет:

<resources>
    <j2se version="1.6+" href="http://java.sun.com/products/autodl/j2se"/>
    <jar href="JavaFXSklad2.jar" main="true" size="164987" download="eager" />
    <jar href="lib/common.jar" size="965131" download="eager" />
    <jar href="lib/ifxjdbc.jar" size="705534" download="eager" />
    <jar href="lib/infra.jar" size="588915" download="eager" />
    <jar href="lib/jdawt.jar" size="726475" download="eager" />
    <jar href="lib/toplink.jar" size="1450414" download="eager" />
    <jar href="lib/weblogic.jar" size="55582010" download="eager" />
</resources>

Важно указать приложению, какой у вас класс приложения. Я не знаю почему.. но я нашел эту структуру в предыдущей версии JavaFX, и это решило мою проблему..

3- если вы используете веб-страницу вместо универсальной.. поэтому просто проверьте, что серийный номер JNLP_content тот же.. потому что каждый раз, когда вы добавляете/удаляете банки в проект, серийный номер будет изменен. рассмотрите также проверку URL.. Я имею в виду этот раздел в HTML:

 function javafxEmbed() {
    dtjava.embed(
        {
            url : 'BSigner_v1.5_release.jnlp',
            placeholder : 'javafx-app-placeholder',
            width : 500,
            height : 100,
            jnlp_content : 'PD94bWwgd0iYnNwc2lnbmVyX3YxLnBrZzRfcmVsZWFzZS5NYWluIiAgbmFtZT0iQlNQU2lnbmVyX3YxLjVfcmVsZWFzZSIgLz4NCiAgPHVwZGF0ZSBjaGVjaz0iYWx3YXlzIi8+DQo8L2pubHA+DQo='
        },
        {
            javafx : '2.2+'
        },
        {}
    );
}

надеюсь, что это поможет вам или кому-либо, кто сталкивается с той же проблемой.

Удачи

person Maher Abuthraa    schedule 13.06.2013