2004.4.25よりアクセス
WindowsとUNIXでは、コマンドライン環境におけるさまざまな違いがあります。Cygwin環境では、基本的にUNIXと同じです。Cygwin環境においてCygwinプログラムだけを使用している限りは問題はありません。しかしながら、Cygwin環境からWindows用プログラムを使用する場合、Windows用プログラムに対してコマンドラインオプションを渡す場合や環境変数の指定内容はWindowsの流儀を使用する必要があります。Cygwin環境においてWindows流儀のコマンドラインオプション記述や環境変数設定をする場合の注意点と対処方法について整理します。
目次
お知らせ(2010/09/09): java_wrapperは、SourceForge.JP上に開発プロジェクトを作成し、今後の開発はSourceForge.JP上の「Cygwin上でJavaコマンドを快適に使用する環境」プロジェクトで継続します。
| バージョン番号 | ファイル | 更新日 | 機能内容 |
|---|---|---|---|
| 1.3.4 | java_wrapper | 2010.09.04 | Cygwin 1.7.6暫定対処の削除、JAVA_HOMEに空白を含むパスを指定したときエラーとなる問題を回避 |
| 1.3.3 | java_wrapper.1.3.3 | 2010.09.03 | -jarオプションに相対パスでjarファイルを指定したときcygpathがエラーとなる問題を回避(Cygwin 1.7.6固有の問題) |
| 1.3.2 | java_wrapper.1.3.2 | 2010.07.14 | コマンドの引数パスにWindowsへ変換すると空白が含まれる場合の問題を回避 |
使い方は、java_wrapperの作成をご覧ください。
| 項目 | Cygwin環境 | Windows環境 |
|---|---|---|
| 複数パス指定時の区切り子 |
: |
; |
| パス中のディレクトリ区切り子 | / | \ |
| ドライブレター記述 | なし | ドライブレター記号+':' |
| 一行で複数コマンド指定時の区切り子 |
; |
|
Windowsは、以下のようなパス指定を使用します。Windowsのパス指定はドライブレターから開始されます。
PATH=C:\WINNT;C:\WINNT\system32;D:\usr\local\bin
^ ^ ^ ^ ^
複数のパスを指定するときは、区切り子に';'を使用
ドライブレターの直後は':'を使用
|
そこで、Windows用に提供されるJavaのコマンドでは、コマンドラインオプションは上述の書式を使用します。
D:\work> java -classpath D:\usr\java\mylib\mylib.jar;D:\work\classes myapp.Main :
Cygwinは、以下のようにUNIXライクなパス指定を使用します。UNIXではパスにドライブレターがなく、全てのパスが'/'(ルート)から開始されます。また、UNIXのコマンド環境では、`;`(セミコロン)は、1行で複数のコマンドを指定する際のコマンド間の区切りを意味します。
PATH=/usr/bin:/usr/local/bin:/usr/java/bin
^ ^
複数のパスを指定するときは、区切り子に':'を使用
|
$ cmd1; cmd2
^
複数のコマンドを一行に書いて実行する場合、コマンドの区切りに';'を使用
|
例:-cp、-classpath、-jar、-sourcepath、-bootclasspath、-extdirs、-d、など
Cygwin環境においてコマンドラインからWindows用Javaコマンドを使用するときの注意点と方法です。
まず、ディレクトリ区切り子にWindows環境の'\'を使うと、Cygwinでは'\'がエスケープ記号のため予期しない動作となります。例えばCygwin上でjavaコマンドの-jarオプションにWindows環境のパス指定方法でJARファイルのパスを指定すると、次のようなエラーが発生します。
torutk$ java -jar c:\j2sdk1.4.2\demo\jfc\Java2D\Java2Demo.jar Unable to access jarfile c:j2sdk1.4.2demojfcJava2DJava2Demo.jar torutk$
幸いにして、Windows用Javaコマンドのほとんどは、ディレクトリ区切り子に'/'を受け付けます。そこで、ディレクトリ区切り子'/'を使用します。
torutk$ java -jar c:/j2sdk1.4.2/demo/jfc/Java2D/Java2Demo.jar : torutk$
UNIXでは文字としての'\'を表すときは、エスケープをキャンセルために"\\"と2つ連続で表現します。
torutk$ java -jar c:\\j2sdk1.4.2\\demo\\jfc\\Java2D\\Java2Demo.jar : torutk$
複数のパスをコマンドラインオプションで渡す場合には、各パスをセミコロン';'で区切って指定します。しかし、Cygwinではセミコロンはコマンドライン上でコマンドを指定する場合の区切りとして扱われてしまうので、エラーとなってしまいます。
torutk$ java -cp c:/cygwin/usr/local/lib/alpha.jar;c:/cygwin/usr/local/lib/beta.jar;. Main
Usage: java [-options] class [args...]
(to execute a class)
or java [-options] -jar jarfile [args...]
(to execute a jar file)
where options include:
-client to select the "client" VM
-server to select the "server" VM
-hotspot is a synonym for the "client" VM [deprecated]
The default VM is client.
-cp <class search path of directories and zip/jar files>
-classpath <class search path of directories and zip/jar files>
A ; separated list of directories, JAR archives,
and ZIP archives to search for class files.
-D<name>=<value>
set a system property
-verbose[:class|gc|jni]
enable verbose output
-version print product version and exit
-showversion print product version and continue
-? -help print this help message
-X print help on non-standard options
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
enable assertions
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
disable assertions
-esa | -enablesystemassertions
enable system assertions
-dsa | -disablesystemassertions
disable system assertions
c:/cygwin/usr/local/lib/beta.jar: 1: Syntax error: "(" unexpected
bash: Main: No such file or directory
torutk$
これもエラーメッセージをちょっと見ただけだと何が原因だか分かりにくいですが、3つのエラーメッセージが表示されています。一つはjavaコマンドのオプション指定が間違っているため使用法が表示されており、二つ目は最初のセミコロンの直後からの文字列c:/usr/local/lib/beta.jarをコマンドとして実行しようとしてのSyntax error、三つ目はさらにその後のセミコロンの後の文字列. Mainを実行しようとしてのエラーです。
セミコロンの前にエスケープ記号'\'をつけて、セミコロンがコマンドラインの区切りとして解釈されないようにします。
torutk$ java -cp c:/cygwin/usr/local/lib/alpha.jar\;c:/cygwin/usr/local/lib/beta.jar\;. Main Hello, Main! I'm an Alpha I'm an Beta torutk$
Cygwin上で仮想的なディレクトリを使用しているときに、いちいちWindows上の実ディレクトリに変換して使用するのは手間がかかってしまいます。
例えば、UNIX風にディレクトリを使用していると、/usr/local/libの下にライブラリファイルを集めます。ここで/usr/localは、Windows上では<Cygwinインストールディレクトリ>\usr\localがマウントされています。他にも設定でいろいろなマウントがあります。これをJavaコマンド実行時には常に実際のパスを意識しなくてはならないのでは作業効率が落ちてしまいます。
Cygwinのコマンドcygpathを使用して、仮想パスから実パスに変換させます。pオプション指定で複数パスの区切り子の変換も自動的にやってくれます。
torutk$ java -cp `cygpath -wp /usr/local/lib/alpha.jar:/usr/local/lib/beta.jar:.` Main Hello, Main! I'm an Alpha I'm an Beta torutk$
環境変数にパスがWindows流儀で記述されていればよいのですが、UNIX流儀で環境変数にパスを指定した場合、Javaコマンドのコマンドラインオプションに環境変数を指定するとエラーが発生します。
torutk$ echo $MYJAR_HOME
/usr/local/lib
torutk$ java -cp $MYJAR_HOME/alpha.jar\;$MYJAR_HOME/beta.jar\;. Main
Hello, Main!
Exception in thread "main" java.lang.NoClassDefFoundError: Alpha
at Main.main(Main.java:5)
torutk$
環境変数には、Windows流儀でパスを指定します。
torutk$ MYJAR_HOME=c:/cygwin/usr/local/lib torutk$ java -cp $MYJAR_HOME/alpha.jar\;$MYJAR_HOME/beta.jar\;. Main Hello, Main! I'm an Alpha I'm an Beta torutk$
Cygwinのツール"cygpath"を使ってUNIX流儀のパス記述をWindows流儀に変換します。
torutk$ MYJAR_HOME=/usr/local/lib torutk$ java -cp `cygpath -wp $MYJAR_HOME/alpha.jar:$MYJAR_HOME/beta.jar:.` Main Hello, Main! I'm an Alpha I'm an Beta torutk$
CygwinでマウントしていたパスがWindows側では空白が含まれる場合、cygpathでCygwinパスをWindowsパスに変換してJavaコマンドのコマンドラインオプションに渡すと、空白によってオプションが分断されエラーとなってしまいます。
例えば、C:\Program Files\Javaを/javaにマウントしていた場合、以下のようになります。
torutk$ java -cp `cygpath -wp /java/lib/alpha.jar` Main
java.lang.NoClassDefFoundError: Files\Java\lib\alfa/jar
Caused by: java.lang.ClassNotFoundException: Files\Java\lib\alfa.jar
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: Files\Java\lib\alpha.jar. Program will exit.
Exception in thread "main"
torutk$
torutk$ java -cp `cygpath -wps /java/lib/alpha.jar` Main Hello, Main! I'm an Alpha torutk$
cygpathに-sオプションを追加します。-sオプションは、Windowsのパスを短い名前(MS-DOS形式:8文字+3文字)に変換する指定です。
Cygwinのコマンド環境を、Teraterm等の汎用ターミナル上で使用するとき、UTF-8に設定していると、WindowsのJavaがCP932で出力するので文字化けとなってしまいます。
ck terminal等、文字コードを自動認識して表示するターミナルソフトウェアを使用する。
javaコマンド実行時、システムプロパティのファイルエンコーディングをUTF-8に変更します。
torutk$ java -Dfile.encoding=UTF-8 Mail
:
torutk$
Cygwinの~/.bashrc に、エイリアスで設定を書いておくのも便利です。
alias javau='java -Dfile.encoding=UTF-8' |
前章で述べた回避策は、いずれもコマンドを使用する都度毎回指定しなくてはなりません。そこで、Javaコマンドを実行する際、コマンドラインオプションの中にあるパス指定を自動的にCygwin環境からWindows環境の流儀に変換するような仕組みを考えていきます。
上記参考URLで紹介した「CygwinでJava」のページをヒントに、java_wrapperスクリプトを作成していきます。いくつか機能を加えています。
これを/usr/local/binの下において、/usr/local/binにいくつかシンボリックリンクを作成します。手作業で作成する例を以下に示します。J2SE SDKに含まれるコマンドについて一通り指定します。
torutk$ cd /usr/local/bin bin$ ln -s java_wrapper java bin$ ln -s java_wrapper javac bin$ ln -s java_wrapper javaw bin$ ln -s java_wrapper jar bin$ ln -s java_wrapper javah bin$ ln -s java_wrapper javap : bin$
面倒なのでJ2SE SDKのコマンドをまとめてシンボリックリンク作成することもできます。
torutk$ cd /usr/local/bin bin$ for cmd in `/bin/ls /usr/java/j2sdk1.5.0/bin/*.exe`; do \ ln -s java_wrapper `basename $cmd .exe`; done bin$
java_wrapperスクリプトにシンボリックリンク作成機能を追加しました(Ver.1.2)。
torutk$ cd /usr/local/bin bin$ ./java_wrapper createsymlinks bin$
JDKのインストール場所を、環境変数JAVA_HOMEに設定します。設定は、~/.bashrcなどに記述します。
JDKのインストール場所が空白を含むパスである場合(例:C:\Program Files\Java\jdk1.6.0_21)、シンボリックリンクかジャンクションで空白を含まないパスから空白を含むパスを参照するようにして、JAVA_HOMEはシンボリックリンク(ジャンクション)のパスを指定すると便利です。
シンボリックリンク作成の例
torutk$ ln -s /cygdrive/c/Program\ Files/Java /java torutk$ export JAVA_HOME=/java/jdk1.6.0_21 torutk$
ジャンクション作成の例(Windows Vista/7)
C:\> mklink /J java C:\Program Files\Java
C:\> dir
:
2010/09/04 03:29 <JUNCTION> java [c:\Program Files\Java]
:
C:\>
※ Windows XPの場合、標準ではジャンクション作成コマンドが搭載されていないので、リソースキットのlinkdコマンドを取得するとよさそうです。
torutk$ export JAVA_HOME=c:/java/jdk1.6.0_21 torutk$
複数バージョンのJDKを持っていて随時切り替えたい場合は、環境設定用のスクリプトを記述します。以下に、JDKのバージョンを指定して環境変数JAVA_HOMEを設定する.bashrcのスクリプトを示します。
function setjdk() {
if [ "$1" = "32" ]; then
echo "- Setting 32bit JAVA Environment"
JDK_BASE=d:/java32
shift
else
echo "- Setting 64bit JAVA Environment"
JDK_BASE=d:/java
fi
case $1 in
1.4)
echo "- Setting JAVA_HOME for JDK1.4.2"
JDK_HOME=$JDK_BASE/j2sdk1.4.2
;;
1.5)
echo "- Setting JAVA_HOME for JDK1.5.0"
JDK_HOME=$JDK_BASE/jdk1.5.0
;;
1.6)
echo "- Setting JAVA_HOME for JDK1.6.0"
JDK_HOME=$JDK_BASE/jdk1.6.0
;;
*)
echo "Usage: setjdk [32] <1.4|1.5|1.6>"
;;
esac
export JAVA_HOME=$JDK_HOME
}
|
32bit版JDK、64bit版JDKのバージョン1.4.2、5.0、6が入っている環境で、Cygwinのコンソール(bash)上でJava(JDK)のパスを切り替えます。
torutk$ javac -d ~torutk -cp /usr/local/lib/alpha.jar:/usr/local/lib/beta.jar Main.java torutk$
パスの指定に、~ユーザ名 とかも指定できるようになりました。Cygwin流にパスが指定できるので、コマンドラインで補完もバシバシ効いて快適です。
Cygwinでjpsコマンドを実行すると、Cygwin以外から実行しているJavaのプロセスのIDが表示されません。(Cygwin 1.7以降と思われる)
Java VMを起動すると、Windows OSでは環境変数TMPまたはTEMPをベースにしたディレクトリにJava VMの起動情報を書き込みます。Cygwinはデフォルトの.bashrc設定で、環境変数TMPとTEMPをunsetしているため、Cygwin以外で実行したJavaの情報とCygwin上で実行したJavaの情報が異なる場所に書き込まれるからです。
Cygwinのデフォルトで生成された$HOME/.bashrc および /etc/profile の中に記述されている unset TMPおよびunset TEMPを削除します。