Java6 Java Web Start(以降JWSに略)アプリケーション内でAttach APIを使うと表題のエラーが発生することが判明した。
以前にも日記で紹介したと思うが、JMX MXBeanのローカルコネクタアドレスを取得するメソッドにて、
public static String getJMXLocalConnectorAddresses() {
List addresses = new ArrayList();
for (VirtualMachineDescriptor desc : VirtualMachine.list()) {
try {
VirtualMachine vm = VirtualMachine.attach(desc.id());
try {
//JMXローカルコネクタアドレスが格納されているプロパティを取得
String connectorAddress = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
addresses.add(connectorAddress);
:
:略
:
} finally {
vm.detach();
}
} catch (AttachNotSupportedException e) {
//アタッチをサポートしていないVMもある
continue;
} catch (IOException e) {
//拒否されるVMもある
continue;
}
}
return addresses.toArray(new String {});
}
赤色で示した行のVirtualMachine.list()に関して、スタンドアロンアプリケーションでは適宜取得できるのだがJWSでは空のリストが戻るのである。
例外もスローされていないので、最初は原因が解らなかったのだが、同メソッドをブレイクダウンして以下のように書き換えることによって、やっとエラーの詳細が判明した。
- VirtualMachine.list()と同等と思われるコード
List<AttachProvider> providers = new ArrayList<AttachProvider>();
for(Iterator iterator = sun.misc.Service.providers(AttachProvider.class, AttachProvider.class,getClassLoader()); iterator.hasNext();) {
try {
providers.add((AttachProvider)iterator.next());
} catch(Throwable throwable) {
System.err.println(throwable);
}
}
for (AttachProvider provider : providers) {
List<VirtualMachineDescriptor> vmList = provider.listVirtualMachines();
:
:
}コード中の変数、vmListに格納される内容はVirtualMachine.list()の結果と同じはずだが、このコードをJWS上で実行すると、イテレータからリストへの追加時に表題のエラーが発生することが解った。
java.lang.UnsatisfiedLinkError: no attach in java.library.path
今のところ原因は不明だが、Sun JDK由来の何らかのライブラリィを使おうとして同パラメタの参照に失敗していると考えられる。
追記:
最初は外部パラメタでライブラリィパスを通してみたのだが、上手くいかなかった。
-Djava.library.path=%JDK_HOME%\jre\bin\attach.dll
ので、本機能で使用すると思われるバイナリ(Windowsであればattach.dll)をattach.jarにアーカイブしてディジタル署名の後、jnlpと共にデプロイすることで空のリストが戻ることは無くなった。
<resources>
<java version="1.6" java-vm-args="-Dcom.sun.management.jmxremote=true"/>
:
:
<nativelib href="lib/attach.jar"/>
</resources>これでOKかと思いきや、今度はVirtualMachine#getAgentProperties()で応答が戻らない。アタッチしたはずのVMへ接続できないようだ。(JDWPデバッグ時)