最近我将Swing应用程序转换为Webstart.这个过程非常简单,但我发现在关闭所有窗口之后,我的应用程序的JVM没有终止.线程转储显示有几个非守护进程线程,特别是Swing的EDT,AWT和一些websart相关的线程.
使用的实际策略是每个窗口在创建时递增计数器,在关闭时递减1.默认关闭操作是DISPOSE_ON_CLOSE.温计数器达到零,我停止所有线程池并释放所有JNI资源.
当我从一个bat文件(相同的JAR)启动应用程序时,它在所有窗口关闭时终止,所以我认为这个问题与Webstart有关.
现在的问题是:
另请参阅用于检测Webstart是否已启动应用程序的后续问题.
给定一个可以工作的远程JNLP(所有jar都可用等),但是你需要在代码上运行一个调试会话.
是否有任何工具可以轻松地在任何合理的现代IDE中创建本地项目,该IDE包含JNLP中所述资源的本地副本,并且可以在调试模式下运行所述代码?假设反编译器可用,这只是让调试会话运行的问题.
是否有任何IDE(Eclipse,Netbeans,IntelliJ,JDeveloper等等 - 甚至是商业产品)只能在给定JNLP URL的情况下执行此操作?
在我的公司,我们使用Java Web Start将客户端软件分发给客户.他们使用不同的Windows版本:XP,Vista和7.
我们在过去通过JWS部署了一个版本最少的版本.我们的最新版本包括几个文件更改,一些罐子不见了,其他的出现了,等等.
我们发现Windows XP计算机上的升级失败,因为JWS仍然试图查找在Web服务器上不再可用的jar文件.我已经检查了我的HTTP服务器日志,并且在应用程序启动期间永远不会从XP机器上访问JNLP文件.如果我在Vista或Windows 7上尝试相同的一切正常,JWS将获取JNLP描述符并在更新可用时下载差异.因此,在XP机器上,只有已知的jar文件才会更新,如果JWS没有从缓存的JNLP文件集中找到某些内容,则会抛出错误.
我编写了一个手动生成JNLP文件的servlet.我在我的servlet代码中使用以下头配置.
response.setDateHeader("Last-Modified", lastModification);
// IE won't download JNLP file if Cache-Control header presents
//response.setHeader("Cache-Control", "no-cache, must-revalidate");
response.setHeader("Expires", "Mon, 26 Jul 1990 05:00:00 GMT");
Run Code Online (Sandbox Code Playgroud)
这使得JNLP文件总是过时的,这应该在每次客户端通过JWS启动时触发重新检查文件.我甚至可以在XP上的缓存查看器中看到这个日期:

我在Oracle的bugreport网站上发现了一个永远无法解决的问题:错误ID:6189106刚刚在Windows XP上对Java7进行了相同的测试,但这个问题仍然存在.但仅在XP上,因为部署缓存的路径中有空白字符("Documents and Settings").有人说,如果我将部署缓存的路径更改为没有空格字符的东西,它将解决问题.嗯,这不是一个真正的解决方案,因为用户几乎不能写到他们的个人资料以外的位置.
因为这个bug存在了这么长时间,我想应该有某种解决方法.我不想每次都告诉客户清除Java缓存并从Web重新安装应用程序.我们希望将来更快的发布周期,这将使其更加恶化.我希望有人对此有个好主意.:|
我们在Tomcat6上启用了基本身份验证.用户在浏览器中进行身份验证,然后启动JNLP以在Java Web Start中启动应用程序.在启动时,java web start尝试从服务器下载jar文件,但它没有使用已经过浏览器验证的同一会话.基于论坛,我试图通过使用sid属性在JNLP中传递会话ID,并在URL中附加.环境受到限制,因此每个请求都需要进行身份验证,我们不能说要排除对未经过身份验证的jar文件的请求.下面是我的JSP创建JNLP文件,任何人都可以请求帮助我们如何继续相同的会话下载已经被浏览器验证的jar.
<% response.setContentType("application/x-java-jnlp-file"); %>
<%= "<?xml version=\"1.0\" encoding=\"utf-8\"?>" %>
<!-- JNLP File for SimpleTableDemo -->
<%
String baseURL = request.getRequestURL().toString().replace(request.getRequestURI(), request.getContextPath());
%>
<jnlp codebase="<%=baseURL%>">
<information>
<title>Simple Table Demo Application</title>
<vendor>Try</vendor>
<description>SimpleTableDemo</description>
<description kind="short">An application that demonstrates a simple table.</description>
</information>
<resources>
<j2se version="1.6+" />
<property name="sid" value="<%=request.getSession().getId()%>" />
<property name="serviceHost" value="<%=request.getServerName()%>"/>
<property name="servicePort" value="<%=request.getServerPort()%>"/>
<jar href="AuthenticateJNLPJars.jar;JSESSIONID=<%=request.getSession().getId()%>" />
</resources>
<application-desc main-class="SimpleTableDemo" >
</application-desc>
</jnlp>
Run Code Online (Sandbox Code Playgroud) 最新的JRE(1.7.0_25)更新后,我的应用程序将不会像以前那样从webstart启动.我没有部署任何较新的jar文件或更改了Web服务器上的JNLP文件,但我无法从webstart启动该应用程序.它可以从IDE运行,也可以从本地jar执行
我试图在控制面板的高级选项卡中禁用所有证书检查等,但错误仍然存在,我不确定这是否与最新JRE中的新安全设置有关,或者是否有其他更改(可能在网络上)服务器?)我不控制Web服务器我只有一个发布应用程序的页面,并且可以访问jar文件的驱动器位置,权限对于驱动器位置是正确的.我现在迷失了什么问题是!我试着辞去罐子并验证签名
我感谢民间所能给予的任何帮助!完整错误如下:
java.lang.NoClassDefFoundError: Could not initialize class sun.security.ec.SunEC
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at sun.security.jca.ProviderConfig$2.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jca.ProviderConfig.doLoadProvider(Unknown Source)
at sun.security.jca.ProviderConfig.getProvider(Unknown Source)
at sun.security.jca.ProviderList.getProvider(Unknown Source)
at sun.security.jca.ProviderList.getService(Unknown Source)
at sun.security.jca.GetInstance.getInstance(Unknown Source)
at java.security.Security.getImpl(Unknown Source)
at java.security.AlgorithmParameters.getInstance(Unknown Source)
at sun.security.x509.AlgorithmId.decodeParams(Unknown Source)
at sun.security.x509.AlgorithmId.<init>(Unknown Source)
at sun.security.x509.AlgorithmId.parse(Unknown Source)
at sun.security.x509.X509Key.parse(Unknown Source)
at sun.security.x509.CertificateX509Key.<init>(Unknown Source)
at sun.security.x509.X509CertInfo.parse(Unknown Source)
at sun.security.x509.X509CertInfo.<init>(Unknown Source)
at sun.security.x509.X509CertImpl.parse(Unknown Source)
at sun.security.x509.X509CertImpl.<init>(Unknown …Run Code Online (Sandbox Code Playgroud) 我正在使用Java Web Start来启动依赖于某些第三方本机库的Java应用程序.然后,这些本机库commonLib使用LoadLibrary/dlopen 加载另一个本机库()作为它们的依赖项.
不使用Web Start时,当本机库位于同一目录中时,一切都按预期工作.
但是,Web Start要求将本机库打包在jar文件中并在jnlp文件中引用,我这样做了:
<!-- Windows OS -->
<resources os="Windows">
<nativelib href="native/native-windows.jar" />
</resource>
<!-- Linux OS -->
<resources os="Linux">
<nativelib href="native/native-linux.jar" />
</resources>
<!-- Mac OSX -->
<resources os="Mac OS X">
<nativelib href="native/native-osx.jar"/>
</resources>
Run Code Online (Sandbox Code Playgroud)
本机库加载正常但它们无法加载它们的依赖项commonLib- C++ LoadLibrary/dlopen调用失败,因为该文件存在于某个jar/cache文件夹中而不是当前库搜索路径中.
在Windows上,我能够commonLib在尝试加载JNI库之前通过在Java中预加载来解决此问题,如下所示:
System.loadLibrary("commonLib");
System.loadLibrary("myNativeLib");
Run Code Online (Sandbox Code Playgroud)
但是,这种方法在OS X上不起作用 - 本机代码中的dlopen失败.dlopen显然不够聪明,如果它已经加载,不再尝试加载库.
是否有一种跨平台的方式来打包和加载依赖于Java Web Start中其他本机库的本机库?
我有代码迭代classLoader.getResources("META-INF/MANIFEST.MF")的结果,以返回类路径上的jar列表.这从1.6.0_18一直到1.7.0_40都很好.现在1.7.0_45通过显示有关混合签名/未签名代码的安全警告弹出窗口来打破此问题.
用于演示问题的小型自包含测试用例:
package testcase;
import java.io.*;
import java.net.*;
import java.util.Enumeration;
import java.util.logging.*;
public class TestCase {
public static void main(String[] args) {
getAllJarUrls();
}
public static void getAllJarUrls() {
try {
final Enumeration<URL> mfUrls = Thread.currentThread().getContextClassLoader().getResources("META-INF/MANIFEST.MF");
while (mfUrls.hasMoreElements()) {
URL jarUrl = mfUrls.nextElement();
if (!jarUrl.getProtocol().equals("jar")) {
continue;
}
try {
System.out.println(jarUrl.toURI());
} catch (URISyntaxException ex) {
Logger.getLogger("testcase").log(Level.SEVERE, null, ex);
}
}
} catch (IOException e) {
Logger.getLogger("testcase").log(Level.SEVERE, null, e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用jnlp(使用有效证书签名的jar)启动它,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://localhost/test" href="test.jnlp"> …Run Code Online (Sandbox Code Playgroud) 在尝试根据传递给HTTP服务器的URL参数动态生成JNLP文件时,我注意到了一件奇怪的事情.如果我的HTML代码中有这样的东西,它可以工作:
<embed type="application/x-java-applet;" launchjnlp="dummy.jnlp"/>
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我%在launchjnlp属性中有一个字符,插件根本不会做任何事情:
<embed type="application/x-java-applet;" launchjnlp="dummy%3f.jnlp"/>
Run Code Online (Sandbox Code Playgroud)
没有错误消息,没有默认的Java启动画面,没有,它默默地失败.(甚至没有尝试检索JNLP文件.)
这是某种安全功能吗?如果是的话,它应该防范什么?
或者它可能是一个直截了当的错误?
更新:使用%实体而不是%符号也不起作用.
更新2:我尝试但未能找到有关该launchjnlp属性的确切语义的任何文档,但整个标记由deployJava.launchWebStartApplication(jnlp)生成,这应该是从浏览器启动Web Start应用程序的"官方"方式.
更新3:只是对此非常清楚:上面的例子只是:一个例子.您可以使用绝对任何 URL(相对,绝对,file://,http://,您为其命名),任何 URL编码的字符,甚至无效的转义序列来观察所描述的行为(尽管在这种情况下它更多或不太合理),实际JNLP文件的存在与否是无关紧要的,因为我们甚至没有达到插件试图加载JNLP文件的程度.
通过将--permit-illegal-access标志传递给VM,我使用JRE build 9-ea + 163运行我的应用程序.现在我想用Java Webstart启动应用程序.第一次尝试
javaws -J--permit-illegal-access <JNLP-Url>
Run Code Online (Sandbox Code Playgroud)
不起作用.我得到同样InaccessibleObjectException有module java.base does not "opens java.util" to unnamed module因为没有国旗.
添加<j2se java-vm-args="--permit-illegal-access" version="9*"/>到JNLP没有帮助.
Webstart支持--permit-illegal-access旗帜吗?
我还可以在JNLP文件中指定标志吗?
顺便说一句,Java 9
javaws https://docs.oracle.com/javase/tutorialJWS/samples/deployment/NotepadJWSProject/Notepad.jnlp
Run Code Online (Sandbox Code Playgroud)
投掷IllegalAccessException,-J--permit-illegal-access也没有帮助.
PS:将env变量设置JAVA_TOOL_OPTIONS为--permit-illegal-access有效,但由于无法访问客户端,因此不是解决方案.
我已经尝试过所有方法
运行应用程序
1)javaws -J-Xdebug -J-Xrunjdwp:transport = dt_socket,server = y,suspend = n,address = 9123 My.jnlp
2)在JAVA_TOOL_OPTIONS中设置相同的选项
3)在JAVAWS_VM_ARGS中设置相同的选项
4)在Java控制面板中设置相同的选项(不带-J)
尝试使用或不使用Xnoagent时使用相同的选项
每一个方式,在我尝试从eclipse连接后这样做 - 它无法连接.当我做netstat -a时 - 它没有显示任何人在9123上收听.
我在Windows 10上
java ×10
java-web-start ×10
jnlp ×5
debugging ×1
distribution ×1
eclipse ×1
ide ×1
java-9 ×1
session ×1
swing ×1