Я пытаюсь перенести свой код с Java 8 на Java 11, этот код ...
private static String readMultiHttpsUrlResultAsString(List<String> mbRecordingIds, String level) throws Exception
{
String result = "";
class NaiveTrustStrategy implements TrustStrategy
{
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
{
return true;
}
};
SSLContext sslcontext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(new NaiveTrustStrategy())
.build();
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(new SSLConnectionSocketFactory(sslcontext))
.build();
StringBuilder sb = new StringBuilder("?recording_ids=");
for(String next:mbRecordingIds)
{
sb.append(next + ";");
}
sb.setLength(sb.length() - 1);
try
{
String url = "https://acousticbrainz.org/api/v1"+level+sb;
HttpGet httpget = new HttpGet(url);
try (CloseableHttpResponse response = httpclient.execute(httpget);)
{
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode!=HttpURLConnection.HTTP_OK)
{
return "";
}
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity);
EntityUtils.consume(entity);
}
}
finally
{
httpclient.close();
}
return result;
}
}
здесь не работает (AdoptOpenJdk) Java 11.0.6 на MacOS,
SSLContext sslcontext = org.apache.http.ssl.SSLContexts.custom()
.loadTrustMaterial(new NaiveTrustStrategy())
.build();
Он без проблем работает в Windows (также с использованием AdoptOpenJdk Java 11.0.6). Одно отличие состоит в том, что версия для Windows использует урезанную jre, созданную из jdk с jlink, тогда как версия для MacOS использует сборку AdoptOpenJDk jre. Сборка MacOS создана с использованием форка InfiniteKinds AppBundler
Это трассировка стека:
java.lang.NoClassDefFoundError: Could not initialize class sun.security.ssl.SSLContextImpl$TLSContext
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at java.base/java.security.Provider$Service.getImplClass(Provider.java:1848)
at java.base/java.security.Provider$Service.newInstance(Provider.java:1824)
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
at java.base/javax.net.ssl.SSLContext.getInstance(SSLContext.java:168)
at org.apache.http.ssl.SSLContextBuilder.build(SSLContextBuilder.java:269)
at com.jthink.songkong.analyse.acousticbrainz.AcousticBrainz.readMultiHttpsUrlResultAsString(AcousticBrainz.java:409)
at com.jthink.songkong.analyse.acousticbrainz.AcousticBrainz.readLowLevelData(AcousticBrainz.java:373)
Я использую Apache Httpclient 4.5.3 и использую эту библиотеку, потому что я получаю данные от веб-службы, для которой требуется использование ssl.
Обновление Я добавил пример теста в свой исходный код из ответа ниже и изменил свою сборку, чтобы сделать его стартовым классом при запуске приложения, и он дает мне эту трассировку стека (когда пакет запускается из командной строки с open
с использованием среды выполнения java, встроенной в пакет с помощью infinitekind appbundler)
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.base/javax.crypto.Cipher.getInstance(Unknown Source)
at java.base/sun.security.ssl.JsseJce.getCipher(Unknown Source)
at java.base/sun.security.ssl.SSLCipher.isTransformationAvailable(Unknown Source)
at java.base/sun.security.ssl.SSLCipher.<init>(Unknown Source)
at java.base/sun.security.ssl.SSLCipher.<clinit>(Unknown Source)
at java.base/sun.security.ssl.CipherSuite.<clinit>(Unknown Source)
at java.base/sun.security.ssl.SSLContextImpl.getApplicableSupportedCipherSuites(Unknown Source)
at java.base/sun.security.ssl.SSLContextImpl$AbstractTLSContext.<clinit>(Unknown Source)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Unknown Source)
at java.base/java.security.Provider$Service.getImplClass(Unknown Source)
at java.base/java.security.Provider$Service.newInstance(Unknown Source)
at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
at java.base/sun.security.jca.GetInstance.getInstance(Unknown Source)
at java.base/javax.net.ssl.SSLContext.getInstance(Unknown Source)
at org.apache.http.ssl.SSLContextBuilder.build(SSLContextBuilder.java:389)
at Example.main(Example.java:23)
Caused by: java.lang.SecurityException: Can not initialize cryptographic mechanism
at java.base/javax.crypto.JceSecurity.<clinit>(Unknown Source)
... 17 more
Caused by: java.lang.SecurityException: Can't read cryptographic policy directory: unlimited
at java.base/javax.crypto.JceSecurity.setupJurisdictionPolicies(Unknown Source)
at java.base/javax.crypto.JceSecurity$1.run(Unknown Source)
at java.base/javax.crypto.JceSecurity$1.run(Unknown Source)
at java.base/java.security.AccessController.doPrivileged(Native Method)
... 18 more
в чем отличие от того, что было у меня раньше, но, может быть, это основная причина или это вводит в заблуждение?
Если я просто запустил java -jar songkong6.9.jar
, он запустит Example и распечатает Loaded без ошибок, если я укажу полный путь из / Library / Java, он также будет работать во всех случаях (Java 11 / Java 14 / JDk и JRE)
Обновление. На основании приведенного ниже ответа я добился определенного прогресса.
JRE, установленная на MacOS, содержит папку conf
, когда JRE добавляется в мой пакет (SongKong) с помощью приложения InfiniteKinds appbundler, у него нет папки conf. У него есть папка lib / security, содержащая default.policy
, но этого, похоже, недостаточно.
pauls-Mac-mini:Home paul$ ls -lR lib/security
total 704
-rw-r--r-- 1 paul admin 1253 22 Apr 14:56 blacklisted.certs
-rw-r--r-- 1 paul admin 103147 22 Apr 14:56 cacerts
-rw-r--r-- 1 paul admin 8979 22 Apr 16:01 default.policy
-rw-r--r-- 1 paul admin 233897 22 Apr 14:56 public_suffix_list.dat
После установки встроенного пакета, если я вручную скопирую папку conf из установленной JRE в домашнюю папку плагина java
e.g
/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home
location, то и код примера, и мой исходный код работают без ошибок при запуске из пакета.
Кроме того, похоже, что он ищет неограниченную папку и ее содержимое (два файла на самом деле одинаковы), поэтому, если я удалю несколько файлов, у меня останется
pauls-Mac-mini:Home paul$ pwd
/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home
pauls-Mac-mini:Home paul$ ls -lR conf
total 0
drwxr-xr-x 3 paul admin 96 22 Apr 15:14 security
conf/security:
total 0
drwxr-xr-x 3 paul admin 96 22 Apr 15:22 policy
conf/security/policy:
total 0
drwxr-xr-x 4 paul admin 128 22 Apr 15:28 unlimited
conf/security/policy/unlimited:
total 16
-rw-r--r-- 1 paul admin 146 22 Apr 15:06 default_US_export.policy
-rw-r--r-- 1 paul admin 193 22 Apr 15:06 default_local.policy
затем он продолжает работать.
Проблема (помимо того, почему это не работает из коробки) заключается в том, что я предполагаю, что я не могу копировать файлы в это место для защищенного приложения времени выполнения, поэтому мне нужно хранить эти файлы политики в другом месте, чтобы их можно было установить как часть сборки appbundler. Поэтому в качестве теста я переименовал папку conf
в папку conf.old
и добавил в пакет следующий параметр
<string>-Djava.security.policy=/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home/conf.old/security/policy/unlimited/default_local.policy</string>
или заменить, а не добавить файл политики
<string>-Djava.security.policy==/Applications/SongKong.app/Contents/PlugIns/adoptopenjdk-11.jre/Contents/Home/conf.old/security/policy/unlimited/default_local.policy</string>
Но это не работает, я пробовал разные значения, но ничего не работает. Единственное, что работает, - это оставить его в подпапке conf, и тогда не имеет значения, передаю я этот параметр или нет. (Я также попытался добавить -Dsecurity.manager
в качестве другого варианта, но это вызвало новую ошибку о разрешениях на ведение журнала.)
-XshowSettings:properties
и добавить его результат в вопрос? stackoverflow.com/a/36045464/3249257 - person Denis Stafichuk   schedule 20.04.2020