GlassFish 付属の JavaDB(Derby) 10.9.1.0 を Java7u51 で起動する

Java7u51の Socket Permission の変更によって49152未満のポート番号でソケットを Listen する場合には明示的にパーミッションを与えることが必要になったようです。

参考: Java™ SE Development Kit 7 Update 51 Release Notes

このため、デフォルトでTCP ポート1527でリッスンする JavaDB も以下のようなエラーを吐いて起動できなくなりました。

C:\glassfish4\glassfish\bin>asadmin start-database
Starting database in Network Server mode on host 0.0.0.0 and port 1527.
Unable to start database.  Please check log in C:\glassfish4\glassfish\databases\derby.log.
Command start-database failed.

実際のログファイルの中はこんな感じ

Sun Feb 02 06:29:10 UTC 2014:
Booting Derby version The Apache Software Foundation - Apache Derby - 10.9.1.0 - (1344872): instance a816c00e-0143-f149-323a-00000c6e8579 
on database directory C:\glassfish4\glassfish\databases\dnd_db  with class loader sun.misc.Launcher$AppClassLoader@1860045 
Loaded from file:/C:/glassfish4/javadb/lib/derby.jar
java.vendor=Oracle Corporation
java.runtime.version=1.7.0_51-b13
user.dir=C:\glassfish4\javadb\bin
derby.system.home=C:\glassfish4\glassfish\databases
Database Class Loader started - derby.database.classpath=''
Sun Feb 02 07:34:10 UTC 2014 : Security manager installed using the Basic server security policy.
Sun Feb 02 07:34:11 UTC 2014 : access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
Sun Feb 02 07:34:11 UTC 2014 : access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
	at java.security.AccessController.checkPermission(AccessController.java:559)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.SecurityManager.checkListen(SecurityManager.java:1134)
	at java.net.ServerSocket.bind(ServerSocket.java:375)
	at java.net.ServerSocket.<init>(ServerSocket.java:237)
	at javax.net.DefaultServerSocketFactory.createServerSocket(ServerSocketFactory.java:231)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.createServerSocket(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.access$000(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.blockingStart(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.executeWork(Unknown Source)
	at org.apache.derby.drda.NetworkServerControl.main(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.sun.enterprise.admin.cli.optional.DerbyControl.invokeNetworkServerControl(DerbyControl.java:158)
	at com.sun.enterprise.admin.cli.optional.DerbyControl.main(DerbyControl.java:245)
java.security.AccessControlException: access denied ("java.net.SocketPermission" "localhost:1527" "listen,resolve")
	at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
	at java.security.AccessController.checkPermission(AccessController.java:559)
	at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
	at java.lang.SecurityManager.checkListen(SecurityManager.java:1134)
	at java.net.ServerSocket.bind(ServerSocket.java:375)
	at java.net.ServerSocket.<init>(ServerSocket.java:237)
	at javax.net.DefaultServerSocketFactory.createServerSocket(ServerSocketFactory.java:231)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.createServerSocket(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.access$000(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl$1.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.blockingStart(Unknown Source)
	at org.apache.derby.impl.drda.NetworkServerControlImpl.executeWork(Unknown Source)
	at org.apache.derby.drda.NetworkServerControl.main(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.sun.enterprise.admin.cli.optional.DerbyControl.invokeNetworkServerControl(DerbyControl.java:158)
	at com.sun.enterprise.admin.cli.optional.DerbyControl.main(DerbyControl.java:245)

今後 JavaDB 側でも対応してくるとは思いますが「なんでもいいからとりあえず起動したい」という方のために私の行った対策を方法を書いておきます。

なお、以下の手順では以下のフォルダに GlassFish がインストールされていると想定しています。これはデフォルトのフォルダですが、もし変えている場合には逐次読み替えてください。

  • C:\glassfish4

※ ちなみに、私の環境は Windows Azuer 上の Windows Server 2012 Datacenter ですがこちらはあまり影響していないと思います。

1. セキュリティポリシーファイルの作成

C:\glassfish4\javadb\bin\security.policy

grant
{
     permission java.net.SocketPermission "localhost:1527", "listen";
     permission java.security.AllPermission;
};

2. JavaDB のJava起動オプションの追加

C:\glassfish4\javadb\bin\NetworkServerControl.bat (Linux の場合には NetworkServerControl)に以下のJava起動オプションを追記します。

セキュリティ・マネージャを有効にする
-Djava.security.manager
セキュリティ・ポリシーファイルのパスの指定
-Djava.security.policy=security.policy

※ ここでは相対パスでカレントディレクトリのファイルを指定しています

Databaseが置いてあるフォルダのパスの指定
-Dderby.system.home=C:\glassfish4\glassfish\databases

※ ここではデフォルトの Dabase の場所を指定しています。Dabaseファイルを別の場所に置かれている場合にはそちらを指定してください

ファイルの実際の行は以下のようになります。
NetworkServerControl.bat

  ...
:runNoClasspath
"%_JAVACMD%" %DERBY_OPTS% -Dderby.system.home=C:\glassfish4\glassfish\databases -Djava.security.manager -Djava.security.policy=security.policy -classpath "%LOCALCLASSPATH%" org.apache.derby.drda.NetworkServerControl %DERBY_ARGS% %DERBY_CMD_LINE_ARGS%
goto end
  ...

3. DERBY_HOME 環境変数のセット

C:\> set DERBY_HOME=C:\glassfish4\javadb

4. JavaDB の起動

先ほど編集したNetworkServerControlでJavaDBを起動します

C:\glassfish4\javadb\bin>NetworkServerControl start
Sun Feb 02 08:14:45 UTC 2014 : Apache Derby Network Server - 10.9.1.0 - (1344872) started and ready to accept connection
s on port 1527

これで無事ポート1527 を Listen して起動できました!