VSCodeでJava開発環境を構築
筆者今まで、EclipseをJavaの開発環境に利用してきましたが、GitHub Copilotの利用をはじめたこともあり、VSCodeに変更しようと考えました。
EclipseではJava8での環境を用いていましたので、それを残してバージョン17と共存させます。合わせてApache Mavenも利用します。
Github Copilotの利用登録
Copilotはフリートライアルがついていますが、基本有料のサービスとなっていますので筆者の覚書き程度に紹介しておきます。
まず、Github copilotから利用登録をします。
登録を終えたら、VSCodeの拡張機能マーケットプレイスから "GitHub Copilot" 拡張機能を検索し、インストールします。
Git Hubへの同期を確認するダイアログがでるので、それにしたがって同期します。出ない場合は一度、Disable にして再度 Enableにすれば表示されると思います。
Copilotの使い方としては、関数名やコメント、前後のコードから判定した、コードのサジェスチョンが表示されます。
採用する場合はTabキー、次候補を表示するには ALT+] 、戻るには ALT+[ を押します(<>だと向きがわかりやすいですが基本的にはカッコの外側に動くと理解すればいいと思います)。
Ctrl+→で、部分的に採用することもできます。また、サジェスチョンの上にマウスカーソルを持っていくとメニューが表示されます。
Ctrl+Enterで、新しいタブに候補の一覧を出力します。
複数のバージョンのJDK
バージョン17未満か、複数のバージョンを共存するには複数のバージョンのJDKが必要です。
理由はこのあと説明しますが、Java17以上ののJDKが必須(執筆時点)です。環境を共存させたいので、JAVA_HOMEの設定は後で行うのでインストール時には省略しましたが、17以上の開発のみならばそのまま設定した方が楽です(その場合はこの後の切替の為の作業も不要です)。
筆者の環境では、Java8のJDKのへのパスが環境変数に登録されていたのでそれを消します。またバージョン17のインストール作業で17のパスも含まれたので合わせて消します。
つまりシステムの環境変数の PATH から次のふたつを削除します。
- C:\Program Files\Eclipse Adoptium\jdk-17.0.6.10-hotspot\bin
- C:\Program Files\Eclipse Foundation\jdk-8.0.302.8-hotspot\bin
PATHに %JAVA_HOME%bin というエントリーを加えます。
環境変数に JAVA_HOME を設定します。ここにJDKのルートまでのパスを設定します。後から切り替えられるようにしますので、初期値はどちらか好きな方でいいです。ここでは17とします。
Eclipseのインストーラーから JAVA_HOME を設定すると最後にファイルセパレータ―の\が入りますので、ここではそのルールにしがたいます。
JAVA_HOME 環境変数は共通認識となっています。そのためJavaを用いるプログラムには JAVA_HOME 環境変数からバイナリを探しに行くように設計されているものがあります。
JAVA_HOME環境変数を変えるPowerShellのスクリプトを作成すると次のようになります。
先ほどPATHに %JAVA_HOME%bin を設定しましたが、この %JAVA_HOME% が展開されるのはOS起動時だけなので、PATH そのものも変更しています。
このスクリプトを利用する際に注意が必要な点は2点あります。ひとつは管理者権限が必要なことです。
もうひとつは、アプリによっては JAVA_HOME や PATH をキャッシュする場合があるということです。そのキャッシュはアプリの再起動でクリアされることもあれば、OSの再起動が必要なこともあるようです。
たとえば、次に紹介するスクリプトを PowerShell で実行したまま画面を閉じずに、java -version コマンドを実行すると変更前のバージョンが表示されます。あらたにプロンプトを生成して実行し直すと変更後のバージョンが表示されます。
change_env.ps1
# 各JDKのルートフォルダへのパスを記述
$jdk_home_17="C:\Program Files\Eclipse Adoptium\jdk-17.0.6.10-hotspot\"
$jdk_home_8="C:\Program Files\Eclipse Foundation\jdk-8.0.302.8-hotspot\"
# 念のため現在のPathバックアップをとる
$timestamp = (Get-Date).ToString("yyyyMMddHHmmss")
$savefile = "c:\bkup_env_" + $timestamp + ".txt"
[Environment]::GetEnvironmentVariable("Path", "Machine") > $savefile
$jdk_version = Read-Host "Enter the JDK version (8 or 17)"
if ($jdk_version -eq "8") {
$jdk_home = $jdk_home_8
$remove_jdk = $jdk_home_17
} elseif ($jdk_version -eq "17") {
$jdk_home = $jdk_home_17
$remove_jdk = $jdk_home_8
} else {
Write-Host "Invalid input. Please enter either 8 or 17."
exit
}
# JAVA_HOME を変更
[Environment]::SetEnvironmentVariable("JAVA_HOME", $jdk_home, "Machine")
Write-Host "JAVA_HOME has been set to: " $jdk_home
# PATHを変更
$oldPath = [Environment]::GetEnvironmentVariable("Path", "Machine")
# 重複登録を避けるために一旦両方のバージョンを削除
$newPath = $oldPath.Replace(";" + $jdk_home_17 + "bin","")
$newPath = $newPath.Replace(";" + $jdk_home_8 + "bin","")
$newPath += ";" + $jdk_home + "bin"
Write-Host "new Path: " + $newPath
# 環境変数変更コマンド部分
[Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
# 確認待ち
Write-Host "Press any key to continue . . ."
Read-Host -KeyPress
VSCodeでJava環境の構築
Extenstion Pack for Java をマーケットプレイスからインストールしたところ次のようなラインナップになりました。
- Extenstion Pack for Java
- Debugger for Java
- Maven for Java
- Test Runner for Java
- Project Manager for Java
- Language Support for Java
Javaのバージョンが17以上が必須である理由は、このExtenstion Pack for Java に含まれる Language Support for Java の要件です。
Language Support for Java は Java Language Server に、 Language Server Protocol(LSP)を使って、問い合わせしハイライトやコード補完をします。
これに用いるJDKのパスを指定します。(17以上の開発環境ならこの指定は省略可能です)
VSCodeの設定ファイル(setting.json)は、スコープがグローバルのものとワークスペースののものがあります。自身の環境にあわせた設定ファイルを選択する必要があります。筆者の場合はdataフォルダを生成してポータブル環境にしていますので、グローバルに設定しました。 キーは "java.jdt.ls.java.home" となります。
settings.json中ではファイルセパレータ―の\はエスケープして\\とする必要があります。
settings.json
{
...
"java.jdt.ls.java.home" : "C:\\Program Files\\Eclipse Adoptium\\jdk-17.0.6.10-hotspot",
...
}
バージョン17以上のJDKが必要ですが、コード補完などの対象範囲は1.5~20までとなっているようです。
開発バージョンの指定
開発するのに使うJDKのバージョンを指定するにはsetting.jsonに次のように記述します。
ここでは、バージョン8をデフォルトにし、17も選択できるようにしました。
setting.json
...
"java.configuration.runtimes": [
{
"name": "JavaSE-17",
"path": "C:\\Program Files\\Eclipse Adoptium\\jdk-17.0.6.10-hotspot"
},
{
"name": "JavaSE-1.8",
"path": "C:\\Program Files\\Eclipse Foundation\\jdk-8.0.302.8-hotspot",
"default": true
}
],
フォルダの初期化
VSCodeの場合は、Javaプロジェクトのフォルダ構成を自分でするする必要があります。
例えばパッケージ名が practice.sample.test なら プロジェクトフォルダの中に「 practice\sample\test 」フォルダを作ります。
一般的なJavaのフォルダ構成では、srcフォルダを作成したい場合と思いますので次のようにします。
まずプロジェクトのルートに、VSCodeの設定フォルダを意味する .vscode フォルダを生成し、その中に setting.json ファイルを作ります。そこに次のように記述します。加えて、外部のライブラリ(jar)を取り込むエントリーと、コンパイル後に出力する為のフォルダの指定をしています。
setting.json
{
"java.project.sourcePaths": [
"src",
],
"java.project.referencedLibraries": [
"lib/**/*.jar",
],
"java.project.outputPath": "bin",
}
この設定により src フォルダがパッケージのルートとなりました。
コマンドパレットからJavaプロジェクトを作成すると、もう少し簡単に初期設定が可能です。Shift+Ctrl+Pで Create JavaProject 、No Build tools 、プロジェクト名を入力すると、先ほど設定した基本的なsrc,bin,lib構成のJavaプロジェクトを作成できます。
開発
環境の準備ができたので、Javaのコードを書きます。Javaのコードファイルは、拡張子を.javaにしてクラスの命名規則に従ってファイル名の最初を大文字にします。
コマンドパレットからプロジェクトの作成をしなかった場合は、この.javaファイルを生成した時点で、システムがJavaプロジェクトを認識し、EXPLORER タブ内に JAVA PROJECTS という子タブが出現します。
JAVA PROJECTの項目では、クラスにワーニングやエラーが発生していると該当のファイル名の右側にその件数が表示されます。
外部のライブラリを利用したい場合は、この JAVA PROJECTS 内の Referenced Libraries の横に表示される+ボタンから追加します。
Debugは左のデバッグボタンから実行する事ができます。この時ブレークポイントも有効になっています。
デバッグの設定をするにはプロジェクトの .vscode フォルダ内にある launch.json にその設定を記述します。
launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Debug (Launch)",
"request": "launch",
"mainClass": "jp.example.DebugClass",
"projectName": "project-name",
"args": ["arg-1", "arg-2"],
"console": "internalConsole",
"stopOnEntry": true
},
{
"type": "java",
"name": "Debug (Launch) 2",
"request": "launch",
"mainClass": "jp.example.DebugClass2",
"projectName": "project-name",
"args": ["arg-1", "arg-2"],
"console": "internalConsole",
"stopOnEntry": true
}
]
}
- type
デバッグのタイプの指定です。java を指定しています。
- name
デバッグ用の設定の名前です。この名前を指定してデバッグを指定するので、Javaファイル名と同じものにするとわかりやすいと思います。argsなどを指定しないデフォルトの状態でよければ「 Current File 」というデバッグの指定の方法もあります。
- request
デバッグ要求のタイプを指定します。launch はプログラムを新しいプロセスとして起動してデバッグを開始します。他には既存のプロセスにアタッチする attach などが指定できます。
- mainClass
mainクラスを指定します。
- args
デバッグ時のコマンドライン引数です。
- console
デバッグコンソールの指定です。internalConsole でVSCodeのコンソールを指定しています。
- stopOnEntry
trueを指定すると、デバッグ時の最初の行にブレークポイントがつきます。
ビルド
ビルド用に Task の登録をします。Terminal から Configure Task を選択します。
tasks.jsonが表示されるので、今回のケースではシェル経由で、コンパイルしてjarファイルにまとめるコマンドを記述しました。
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build jar file",
"type": "shell",
"command": "javac -encoding UTF-8 -d bin src/test/sample/*.java && jar -cvfe myApp.jar MyApp -C bin/ .",
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": {
"owner": "java",
"fileLocation": ["absolute"],
"pattern": {
"regexp": "^(\\[ERROR\\]|\\[WARNING\\])\\s*(.*?)\\s*\\[(.*?)\\]\\s*->\\s*\\[(.*?)\\]$",
"file": 2,
"severity": 1,
"message": 3
}
}
}
]
}
上記のjsonの説明をしていきます。まず、タスクは tasks 配列の中のひとつのオブジェクトとして定義され、label にその名称を書きます。
- type
これはシェルコマンドを意味します。type が shell の時 次で紹介する command を指定することができます。
- command
シェルで実行するコマンドを記述します。ここでは javac でコンパイルして、jar でまとめています。
最初に設定した環境変数の PATH が影響します。複数のバージョンが混在している場合は意図したバージョンで javac が実行されているかチェックしましょう。
- group
これはタスクをビルドグループに設定させるために、kind を build に指定しています。また、isDefault に True を入れることでデフォルトのビルドタスクとしています。
- presentation
presentationはオプションの項目で、reveal を always にすることでタスク実行内容を常にターミナルに表示し、その際は常に新しいパネルが作成されるようにしてある設定です。
- problemMatcher
problemMatcherはタスク実行時に出力されたメッセージがエラーや警告だった場合に検出するパターンを指定します。ここでは、owner に java を指定して javaのマッチャ―であることを指定し、pattern の regexp つまり正規表現によって文字列を指定しています。
正規表現のグループ番号を、file(ファイル名)、serverity(重要度)、message(メッセージ)として指定しています。
TypeScriptからの出力用のマッチャ―は $tsc など事前定義されたマッチャ―名を設定することもできす。
こちらもオプションです。
Maven
次はMavenプロジェクトを生成します。さきほど No build tools を選択した箇所で、Mavenを選択するようにします。その後、maven-archetype-quickstart 、1.4 と選択していきます。
1.4の部分はバージョンなので、特に意図がなければ一番おおきいものを選択します。
その後GroupIDとartifactId入力を求められます。GroupIDはパッケージ名の共通部分となる部分を、artifactIdにはアプリの識別となるIDを入力します。詳しくは、以前Mavenレポジトリからjarファイルを取得した際の記事を参考にしてください。
最後にプロジェクトを保存するフォルダを指定します。ここで指定された場所にartifactIdで設定した名前でプロジェクトが作成されます。
依存を追加したい場合はコマンドパレット(Shift+Ctrl+P)から、Maven add Dependency からライブラリを検索追加することができます。また、通常通りpom.xmlに記述しても問題ありません。
デフォルトだと、これらのライブラリはユーザーホーム(c:\ユーザー\ユーザー名\).m2フォルダに保存されます。
Mavenでビルドをする際は、Mavenのタブからプロジェクトを選択して右クリックして選択できるRun Maven Commandからか、コマンドパレットから実行できます。
ライブラリをダウンロードするだけなら、mavenのバイナリは不要ですが、ビルドのコマンドを実行するにはMavenのバイナリが必要で、さらにMaven Excutable Pathにmvn.cmdへのパスを指定しなければいけません。
こちらも先に紹介したMavenの記事に書いてありますが、Apache Mavenからダウンロードし展開したbinフォルダ内にそれは存在します。
mvn clean を実行した後、mvn package を実行すると自身が作成したプロジェクトのjarファイルが、pom.xml内の設定に従ってtargetフォルダ内に生成されます。
ちなみに、依存するライブラリもすべて含めてひとつのjarファイルにバンドルする場合は、pom.xmlのbildのセクションを次のように変更します。
some.package.EntryPointClassの部分は自身の環境に差し替えて下さい。
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>some.package.EntryPointClass</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Git
VSCodeにはGitが備わっています。左側のバー検索ボタンの下にあるアイコンがgit用になるので、そこから「 Initialize repository 」をクリックします。(= git init)
stagingの内容は Changes に掲載されますので右クリックから Stage All Changes を選択します(= git add -A)。
コミットはボタンになっているので、上段の枠にコミットメッセージを入れて押します。(= git commit -m "comment")
あとは流れに沿っていけば、Git Hubにアップロードされます。別の場所にアップデートしたい場合は、... ボタンのAdd Remote から操作します。
EclipseとVSCocdeの共存環境を作る
EclipseのsrcフォルダをVSCodeから開けば、VSCodeからコードを修正することは可能なのですが、編集した内容がEclipseに伝わらず再読み込みが必要だったりすることがあり、行儀が悪いと諦めました。
別々の環境を作り、gitを経由して同期するのが間違いが少ないと思いましたので、その環境づくりをします。
Java用のエクステンションの設定を終え、プロジェクトを作成する前の段階から始めます。
- clone
まず、プロジェクトのcloneを作成します。VSCodeを立ち上げて何もフォルダを開いていない状態で(開いている場合はファイルタブからフォルダを閉じます)、gitのメニューを表示させると「 Clone Repository 」ボタンが表示されると思いますのでそれをクリックします。
開いたダイアログにレポジトリのアドレスを入力します。
保存先を聞かれます。「 プロジェクトのルートフォルダを作成したい親フォルダ 」を指定します。
フォルダを開くか尋ねてくるのでそのまま開きます。
- フォルダ構成の確認
Eclipseのプロジェクトでgitを運用しているプロジェクトをクローンした時、次のような構造になっていたとします。
VSCodeプロジェクトフォルダ │ ├─── .git │ ├─── Eclispseプロジェクトフォルダ │ ├── src │ └── .gitignore
ちなみに.gitignoreでは 次のように定義されているため。binフォルダや.project等のEclipse用の設定ファイルが除外されています。
.gitignore
/bin/ /.classpath /.settings/ /.project
- Javaプロジェクトの認識
任意のJavaファイルを開いてJavaプロジェクトを自動生成させます。先ほども書きましたが、先にExtension Pack Javaがインストールされている必要があります。
- 設定フォルダとファイルの作成
プロジェクトのルートにVSCode用の設定ファイル用のフォルダ ./vscode を生成します。その中に settings.jsonを生成します。
後で書く、拡張ライブラリのインポート等の作業をすると自動生成されますので、既存の場合はそれを利用してください。
- .gitignoreファイル
VSCodeのプロジェクトはEclipseのプロジェクトのひとつ上となります。ここに .vscode フォルダが作成されます。これを .gitignoreファイルに記述して除外するのですが、Eclipse側の .gitignore ファイルはひとつ下の階層にあるので使えません。
あらたに .gitignoreファイルを生成し、そこへ .vscodeフォルダの除外を記述します。
VSCodeプロジェクトフォルダ │ ├─── .git │ ├─── Eclispseプロジェクトフォルダ │ ├── src │ └── .gitignore ├─── .vscode └─── .gitignore
.gitignoreファイルは階層別に複数存在しても意図したように機能します。
- 外部ライブラリの参照設定
JJAVA PROJECTS の「 Referenced Libraries 」の + ボタンから外部Jarを取り込みます。
もし、Eclipseでプロジェクトフォルダを参照をしていた場合は、VSCodeでは非対応のようですので、該当のプロジェクトをJarファイルにまとめてjarファイルとして設定する必要があります。
以上の設定で、EclipseとVSCodeの共存環境ができました。
5C問題
今のところ大きな影響はでてないのですが、VSCodeで文字コードがSJISのプロジェクトだと、文字コード化した際5C(\)を含んだ文字列がエラーとして検出されてしまうようです。
5Cを含んだ文字列に対してこのエラーがでるのですが、ファイルの中身を参照してSJISだという事が判明するとエラーが消える不思議な挙動になっています。
気になるならコードの文字コードをUTF-8にするしかなさそうです。
また別件ですが、設定をSJISにしておくとgitのコミットメッセージの入力もデフォルトでSJISがセットされてしまいます。通常gitのコメントはUTF-8で記述するようになっていると思いますので、保存の再にUTF-8を指定しないと、今度はコミットメッセージが文字化けします。
今回の記事を書くにあたり、次のページなどを参考にさせていただきました。ありがとうございました。