• ベストアンサー

システム環境変数の削除の自動化(バッチ化)

●質問内容 システム環境変数を変更する場合(WindowsXP時)、 「スタート」⇒「設定」⇒「コントロールパネル」⇒「システム」の 「システムのプロパティ」画面の「詳細設定」タグ内の「環境変数」ボタンを 押下して「環境変数」画面にて新規/編集/削除を実施すると思います。 システム環境変数の削除を行うにあたり上記一連操作をバッチファイル 等の単純操作にて実施したいと考えているのですがどのようにすれば実現できるでしょうか? 条件は以下の通りです。 ・OSはWindowsXPもしくはWindows2000。 ・削除するシステム環境変数名は決まっている。 ・ログオン/ログインや再起動は行わずに削除情報を反映させたい。 ●質問内容補足 自分で調べた範囲ではシステム環境変数の新規/編集であれば Windows2000のリソースキット中のsetx.exeというプログラムを 利用すれば可能だということが分かりました。 このHPで言っているように削除もバッチ処理で行いたいのです。 参考HP<<http://chinpindo.blog11.fc2.com/blog-entry-61.html#more>> お手数ですがご回答頂けると幸いです。 よろしくお願いいたします。

  • xf710
  • お礼率67% (21/31)

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.6

★バッチファイル等の単純操作だけでは実現不可能。 ・まず、『SendMessageTimeout』関数は、????.reg ファイルに記述する命令ではありません。 ・回答者 No.5 番さんの『アドバイス』通りです。 ・よって、バッチファイルで実行を反映させるには簡単なアプリケーションを作成して  それを実行させます。下にそのCサンプルを紹介。→テスト済み(正常に動作した) Cサンプル: #include <stdio.h> #include <windows.h> int main( VOID ) {  DWORD dwReturnValue;  LRESULT Ret;    printf( "★レジストリ内容を反映させています...\n" );    Ret = SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0,   (LPARAM)TEXT("Environment"), SMTO_ABORTIFHUNG,   5000, &dwReturnValue );    if ( Ret == 0 ){   printf( "\n×正常にレジストリ内容を反映できませんでした。\n" );  }  else{   printf( "\n★正常にレジストリ内容を反映しました。\n" );  }  return( 0 ); } 方法: ・回答 No.4 の補足にある ????.reg ファイルの内容は3行で良い。 ・上記のCサンプルを元に『コンソール・アプリケーション』を作る。→コマンド名(RegRefreshなど) ・バッチファイルで、????.reg と RegRefresh を記述すれば実現可能です。 ・ただし、現在開いている『コマンド・プロンプト』には反映しませんので、『コマンド・プロンプト』を  起動し直す必要があります。→システムの環境変数は反映します。 ・また、ソフトによっては『WM_SETTINGCHANGE』メッセージを受け取らない仕組みならば、上記方法では  反映されることはありません。→この場合は再起動などが必要です。 まとめ: ・レジストリ操作ファイルと一緒に書かずに、別にコマンドを作成します。 ・以上。おわり。→サンプルは、C言語ソースです。

xf710
質問者

補足

ご丁寧なご回答ありがとうございます。 ANo.5の回答を見た後、 私がプログラムを組んだものとご明示頂いたサンプルソースが ほぼ同じ内容だった為、自分が合っていると確認できました。 また『コンソール・アプリケーション』を作る等、 補足情報が詳細で良く理解することが出来ました。 最後に二点だけ質問させて下さい。 (1) サンプルソース内に『(LPARAM)TEXT("Environment")』という 記述がありましたが、このTEXTというのは何を表しているのでしょうか? (以前教えて頂いた参考HPのサンプルにはTEXTの記述はありませんでした。) (2) 上記サンプルソースをコンパイルして作成したEXEをダブルクリックしたところ、 処理が終了した時点でコマンドプロンプトが閉じてしまい、 printf文で表示している内容が『"★レジストリ内容を反映させています』しか確認できませんでした。 サンプルソースのreturn(0)の前に『fflush(stdin); 』という Enterキーを押さないとコマンドプロンプトが次行の処理に 移らない記述を書いても効果がありませんでした。 EXEを直接実行(ダブルクリック)した後、printf文を確認できるように 処理を止めるにはどうしたらよいでしょうか? 何度も伺ってしまい申し訳ありません。

その他の回答 (7)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.8

EXEファイル自体で入力待ちをしたいということなら、getchar()あたりを 使うことがポピュラーではないでしょうか。 fflushはバッファにたまっているデータを掃きだすことをするので、 入力待ちにはなりません。ていうか fflush(stdin) って規格上未定義ですよ。 いっそのこと MessageBox を使って待つというのはダメでしょうか? 対応のライブラリをきちんとリンクしておけば、main() で始まる通常の コンソールプログラムでもメッセージボックスを出すことはできますよ。

xf710
質問者

お礼

最初に質問した際には、 EXE自体で入力待ちにしたいと考えていたのでご回答助かりました。 fflush(stdin)で止められるような事を記述しているHPがあって、 それで止めれた事があったのでそう信じてたのですが違うんですね… getchar()、MessageBox両方試してみたいと思います。 ご回答ありがとうございました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★最後の質問について ・『TEXT』はマクロ関数です。 ・これは、ビルド(コンパイル)時に UNICODE が定義されていれば、文字列定数に『L』を追加して  UNICODE の定数に解釈します。また、UNICODE が定義されていないと『シフトJISコード』で解釈  します。つまり、ビルド(コンパイル)時に UNICODE が定義されているかどうかで簡単に Unicode  への対応ができるためのマクロです。『TEXT』マクロを使うと後で国際向けのプログラムに簡単に  変身できます。(参考: http://wisdom.sakura.ne.jp/system/winapi/win32/win4.html ) ・バッチファイルの中で一時停止したいのならば『pause』という命令を1行記述します。  これで、一時停止しますので『★正常にレジストリ内容を反映しました。』という文字列を確認  できるようになります。何かキーを押すと続きの処理を行います。→最後だと、画面が閉じます。 ●バッチ内容 ????.reg RegRefresh.exe pause ※上記の3行で最後に一時停止しますので、確認メッセージを表示できます。 余談: ・API関数の『SetWindowText』には、『SetWindowTextA』と『SetWindowTextW』の2つがあります。 ・『SetWindowTextA』は『シフトJISコード』対応の文字列を引数に取ります。 ・『SetWindowTextW』は『Unicodeコード』対応の文字列を引数に取ります。 ・よって、SetWindowText 関数を使うと、定数 UNICODE の定義によってどちらの関数を  ビルド(コンパイル)時にリンクするかが決定します。これと同じです。『TEXT』マクロの機能は。 ・以上。分かりましたか? 最後に: ・以前『C言語を用いた環境変数の作成/削除方法』で質問した xf710 さんですね。 ・そのときに http://support.microsoft.com/kb/104011/ja を紹介しましたね。忘れていました。

xf710
質問者

お礼

お礼が遅くなり申し訳ありません。 TEXTの意味及びバッチファイルについてや余談の内容等、 分かり易い解説を本当にありがとうございました。 やりたい事が実現できて大変助かりました。 またAPI関数等様々な知識を学んでいきたいと感じられました。 しかも覚えて質問した内容まで覚えていられるとは…恐縮です。 また何か質問する事がありましたら何卒よろしくお願いいたします。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

> (Win32 API『SendMessageTimeout』関数はレジストリ操作ファイルと > 一緒に書かず、別に作成するものなのでしょうか?) レジストリ操作ファイルにAPIを書いても無視されるかエラーになるだけだと思います。 Windows上で動くプログラムは通常はウィンドウメッセージというもののやり取りをしていて、 SendMessageTimeOutというのは任意のウィンドウにウィンドウメッセージを投げるものです。 ですから、このメッセージを投げるプログラムが何らかの形で必要になります。 バッチとかwshではできないような気がします。 CなりVisual Basic、はたまたDelphiなどで(ほかにもできるものはありますが) ウィンドウメッセージを投げるプログラムを作らなければならないのではないでしょうか? あと、このメッセージを投げたとしてもメッセージを受ける側のプログラムのつくりによっては 環境変数が書き換えられたとしてもそれを認識しない可能性があります。

xf710
質問者

お礼

ご回答ありがとうございます。 『SendMessageTimeout』関数はWin32API関数だったんですね。 そのままレジストリ操作ファイルに書くような書式ではないと 薄々気付いてはいたのですが…調査不足ですいませんでした。 この回答見てからプログラムを組んでEXEファイルを 作成したらシステム環境変数を反映させる事が出来ました。 ありがとうございます。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★簡単な解説 ・まず、Win32 API『SendMessageTimeout』関数で複数のウィンドウへメッセージを送信します。 ・また、『WM_SETTINGCHANGE』メッセージは、システム全体の設定を変更したときに、再起動など  しないで設定内容を反映したい場合に送ります。つまり、再起動などしないですべてのトップ  ウインドウに『更新したよ』というメッセージを送るのです。なお、昔は『WM_WININICHANGE』  で『WIN.ini』ファイルを更新するメッセージがありました。これの、レジストリ版って事だ。 ★『WM_SETTINGCHANGE』メッセージ ●WPARAM ・アプリケーションが発行するときは 0 を指定 ●LPARAM ・更新する部分のレジストリ名(WIN.iniのセクション名)の文字列を指定 ★『SendMessageTimeout』関数 LRESULT SendMessageTimeout(  HWND hWnd, // ウィンドウのハンドル  UINT Msg, // メッセージ  WPARAM wParam, // メッセージの最初のパラメータ  LPARAM lParam, // メッセージの2番目のパラメータ  UINT fuFlags, // 送信オプション  UINT uTimeout, // タイムアウト期間(ms)  PDWORD_PTR lpdwResult // 同期呼び出しの戻り値 ); ●参考URLの説明 ・『hWnd』に『HWND_BROADCAST』を指定すると、システム内の全てのトップ・ウィンドウに送信 ・『Msg』に『WM_SETTINGCHANGE』を指定。 ←システムの更新を反映させるため ・『wParam』に 0 を指定。 ←アプリケーションが発行するから ・『lParam』に "Environment" の文字列を指定。 ←環境変数を更新するから ・『fuFlags』に『SMTO_ABORTIFHUNG』を指定。 ←ハングアップ状態のとき、即、制御を戻す ・『uTimeout』に『5000ms』を指定。 ←ハングアップと判断するまでの時間 ・『lpdwResult』に『dwReturnValue』を指定。 ←メッセージの処理結果を格納 ・以上。おわり。

参考URL:
http://msdn.microsoft.com/library/ja/jpwinui/html/_win32_sendmessagetimeout.asp?frame=true
xf710
質問者

補足

ご丁寧に解説して頂きありがとうございました。 早速、システム環境変数を削除する「○○○.rsg」を 以下のように内容を変更して同ファイルをダブルクリックしたところ、「レジストリに正しく入力されました」とメッセージが出るものの、 環境変数削除が反映されていないように思えます。 何が悪いのか分からない為、ご指摘頂けると幸いです。 (Win32 API『SendMessageTimeout』関数はレジストリ操作ファイルと 一緒に書かず、別に作成するものなのでしょうか?) ●○○○.rsgファイルの内容 1. Windows Registry Editor Version 5.00 2. [HKEY_CURRENT_USER\Environment] 3. "AAA"=- 4. 5. Windows Registry Editor Version 5.00 6. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 7. 0, "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue); (※左側数字(Ex 1.)は行番号。) ●システム環境削除が反映されたかの確認方法 上記○○○.rsgファイルダブルクリック後、 コマンドプロンプトを開いて「set AAA」と打ち込んだところ、 削除前の値である「AAA=aaa」が表示されてしまいました。 (※試しにAAAという環境変数を操作しています。)

noname#219128
noname#219128
回答No.3

VBScript使っていいなら以下のような感じでできると思います。 Option Explicit Set objShell = WScript.CreateObject("WScript.Shell") Set sysEnv = objShell.Environment("System") sysEnv.Remove("削除する環境変数名") Set sysEnv = Nothing Set objShell = Nothing

参考URL:
http://www.atmarkit.co.jp/fwin2k/operation/wsh06/wsh06_02.html
xf710
質問者

お礼

ご回答ありがとうございました。 今回VBScriptは用いずに実施させたいので利用できませんが、 別方法でも実現可能だと勉強になりました。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★再起動せずに変更を有効にする方法 ・システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします。 ・レジストリ操作によってシステム環境変数を操作する方法を知っているのなら出来ますね。 ・なお、環境変数の文字列操作は経験的に面倒ですよ。→検索、追加、挿入、削除といろいろね。 ・短いですがアドバイスはこれで終わりです。 ・下に『参考URL』を載せておきます。→『詳細』部分に『再起動せずに変更を有効にする方法』があるよ。

参考URL:
http://support.microsoft.com/kb/104011/ja
xf710
質問者

補足

ご回答ありがとうございます。 同HPも質問前に検索して既に見つけていたのですが、 再起動せずに変更を有効にする方法が分かりません。 >・システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします。 参考URLに記述されていた以下の本文内容 「関連するアプリケーション (エクスプローラ、プログラム マネージャ、タスク マネージャ、コントロール パネルなど) が更新を行えるように、システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします」 の中で、 ・システム内のすべてのウィンドウ ・WM_SETTINGCHANGE メッセージをブロードキャストします という文章の意味がいまいち分かりません。 「システム内のすべてのウィンドウ」とは環境変数変更後に使用するアプリケーションを示すのでしょうか? またWM_SETTINGCHANGEメッセージを具体的にどのようにブロードキャストしたらよいかその方法が分かりません。 (教えていただいた参考URLに以下の例が書かれていましたが、 どの記述が何の意味を示すのか分からず困っています。) SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue); ちなみにシステム環境変数の削除には以下の記述を行った.reg拡張子ファイルを作成し 同ファイルををダブルクリックして削除しました。 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment] "AAA"=- >・レジストリ操作によってシステム環境変数を操作する方法を知っているのなら出来ますね。 すいません。下記URLを参考に環境変数の追加、変更、削除までは できる様になったのですが、再起動せず変更を有効にする方法は 分かりません。 参考URL:http://www.higaitaisaku.com/patchfile.html >・なお、環境変数の文字列操作は経験的に面倒ですよ。→検索、追加、挿入、削除といろいろね。 少々実施した私でも面倒だと感じました。 なので長くやられているとより一層そう感じますよね、きっと。 追加質問となってしまい申し訳ありません。 ご回答の程、よろしくお願いいたします。

  • JAWS55
  • ベストアンサー率38% (176/452)
回答No.1
xf710
質問者

補足

早急なご回答ありがとうございます。 残念ながらこちらのHPでは実施したい内容と条件が異なります。 このページは質問する前に既に参照して実行していたのですが、 システム環境変数名が削除されるのではなく、 システム環境変数値が空になるだけで システム環境変数名自体は残ってしまいます。 つまりシステム環境変数値が空のシステム環境変数が存在する事になります。 実施したい内容としては、 あるシステム環境変数自体を削除したいということです。 ●追加質問 レジストリ操作によってシステム環境変数を削除する方法は分かりました。 但しレジストリを変更後、再起動せずに変更を有効にする方法が分かりません。 こちらも知ってる方がいらっしゃったら合わせてアドバイスを頂けると 幸いです。

関連するQ&A

  • ユーザー環境変数をバッチファイルのような形で設定するには?

    OSがXPの場合、手操作にてユーザー環境変数は、 システムのプロパティ画面⇒詳細設定タグ⇒環境変数ボタン押下 ⇒ユーザー環境変数の新規ボタンを押下 ⇒変数名、変数値を設定。 といった手順で設定すると思うのですが、 この手操作をバッチファイルのような形で自動設定したいと考えています。 (多数のユーザーに同じ設定を行いたい為、手操作を自動化したい。) (多分レジストリ操作をする必要があると思うのですが実施方法が よく分かりません。) 設定したいのは、 変数名:OVER_RIDE(仮名称) 変数値:C:\Documents and Settings\(ユーザー名) という内容のユーザー環境変数になります。 設定するOSはXPと2000のどちらかになるので、 それぞれ設定方法が異なる場合、 それぞれのバッチファイルを作って適応したいと考えています。 ご回答の程、よろしくお願いいたします。

  • バッチファイルで環境変数が設定されません

    よろしくお願いいたします。 Windows XP Pro の command.com において、バッチファイルの中で set コマンドを使って環境変数を設定しても、バッチから抜けると環境変数の設定ができていません。 バッチ終了後の環境変数は全てバッチ開始前と同じ状態です。 command.com のプロンプトで set コマンドを実行すると、環境変数はセットした内容に変化もしくは追加されます。 cmd.exe ではバッチからでもプロンプトからでも set コマンドで環境変数を操作できます。 なぜ command.com 上のバッチから操作できないのかわからず、不便でかないません。 アドバイスをよろしくお願いいたします。 @echo off set foo=word path=c:\ echo %foo% echo %path% 上記バッチを実行すると word c:\ と表示されますが、set コマンドで確認すると FOO は存在しません PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;... と表示されます。 これはバッチ実行前の値です。

  • Win10の環境変数について誤削除の変数は無いか?

    Win10の環境変数について 設定(歯車アイコン)→システム→詳細情報→右端の関連設定→システムの詳細設定をクリックするとシステムのプロパティ画面が表示され、詳細設定タブ→環境変数(下側にあるアイコン)をクリックし環境変数の画面に入れます。OneDriveを使用しないのでユーザーの環境変数からOneDriveを削除しました。(他のクラウドを使用)ユーザーの環境変数と、下側のシステム環境変数の変数を間違って削除していないか、変数で何か抜けたものが無いか教えてください。Windows10 64bit HOME 20H2正規版エディションです。 ユーザーの環境変数 上からPath、TEMP、TMP システム環境変数 上からNUMBER_OF_PROCESSORS、OS、Path、PATHEXT、PROCESSOR_ARCHITECTURE、PROCESSOR_IDENTIFIER、PROCESSOR_LEVEL、PROCESSOR_REVISION、PSModulePath、TEMP、TMP、USERNAME、windir という並びになっています。

  • システム環境変数の設定

    通常、コントロールパネルのシステムにて設定するシステム環境変数(PATH)を、バッチファイルからコマンドを使用して設定したいのですが、何か良い方法は無いでしょうか?

  • setXコマンドがうまくバッチで動かない・・・

    setXコマンドをバッチファイルの中に書いてシステム環境変数に登録させているのですが、なぜかユーザー環境変数にセットされます。 BATの中にはこんな感じです。 Pathに追記をする要領です。 SETX PATH "%PATH%;C:\Extra\Shibin" -m -mでシステムに登録だと思ってはいたのですが・・・間違っていますでしょうか? Win7 64びtt版です

  • javaのpath環境変数がうまくできません

    path環境変数がなかなか設定できません。 『システム変数の編集』で どうも設定を間違っているらしく、 C:\j2re1.4.2\binを追加するのに 前にあったはずの、C:\WINDOWS~~~ を削除してしまって、なんて入れれば環境変数が うまくできるかわからなくなってしまいました。 誰かお願いします。

    • ベストアンサー
    • Java
  • 環境変数について

    ◇環境変数をセットしたい場合 WindowsXPを使っています。 コントロールパネル-システムの環境変数から設定しましたが、 ログオフや再起動しないと反映されないのでしょうか? ユーザー環境変数やシステム環境変数の違いも影響有るのでしょうか? AA C:\ PATH %AA%;として、%で括れば、登録済みの環境変数も使えるのでしょうか?

  • バッチでのレジストリPath環境変数方法

    バッチでのレジストリPath環境変数方法 お世話になっております。 レジストリのPath環境変数をバッチで変更しようとています。 バッチ処理の動きとしては、下記の処理をするバッチを 作りたいのですが、上手くいきません。 ≪処理≫ 1、reg queryで、指定されたPath設定を検索 2、if errorlevel ~ 構文で   if errorlevel 1 goto tran1   goto tran2     2-1、指定されたPath設定がなければ、3へ。   2-2、指定されたPath設定があれば、 4へ。     (指定されたPath環境変数は設定済み)    3、reg addで、Path環境変数を変更する 4、次の処理実施   (指定されたPath環境変数は設定済) 具体的な処理内容は、下記のような記述をしてます。 ≪バッチ内容(例)≫ @echo off reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v path | findstr /i "C:\Program Files\navnt" if errorlevel 1 goto tran1 goto tran2 :tran1 reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v path /t REG_EXPAND_SZ /d "%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\Program Files\navnt" /f :tran2 echo 次の処理へ しかし、実行すると、全てTran2へ行く処理になってしまい、Tran1への処理になりません。    ※reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v path | findstr /i "C:\Program Files\navnt"  | findstr /i "C:\Program Files\navnt" 箇所の、findstr が上手く機能してないと思ってます。   オプションもいくつか追加して試しましたが、上手くいきませんでした。  (試)  findstr の /c:文字列 を追加  ⇒ 結果、NG ~ | findstr /i /c:"C:\Program Files\navnt" findstrの記述が原因と思いますが、 ●tran1の reg addへ飛ぶ処理の記述をご教授頂けますか? 宜しくお願い致します。

  • ユーザ環境変数とシステム環境変数の違い

    ユーザ環境変数とシステム環境変数の違いって何ですか? CLASSPATHを設定しようとしているのですが、本ではシステム環境変数に設定していますが、同じような目的のCLASSPATHの設定でもネットの解説などではユーザ環境変数に設定していたりして、この疑問が出てきました。 よろしくお願いします。

  • システム環境変数と、ユーザー環境変数。

    こんにちわ。 昨夜からちょっと困ってパニックになっています。 1から書いていきます。 読みにくかったら、申し訳ございません。 コンパイルしたJanken.classが、 C:\java>java Janken で作動せず、 java.lang.NoClassDefFoundErrorのエラーが出ました。 そこで、参考書を見て環境変数に問題があるということなので、 環境変数を触ったのですが、それでも上手く行かずネットで検索をかけて調べたところ、 "システム環境変数"と"ユーザー環境変数"の設定を変えました。(osは、XPです。) それ以来、 ----------------- C:java>java Janken 'java'は、内部コマンドまたは、外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 C:\java ---------------- と、なります。 コンパイルも出来ません。 「システム環境変数には、触れてはいけない」と 検索した先のページには、書かれていまして、 ユーザー環境変数と間違って、システム環境変数を変えていたことになります。 元に戻すには、PCの初期化が必要なのでしょうか? また、参考書の通りコマンドプロンプトに打つとこう表示されます。 ----------- C:\Documents and Settings\Owner>set CLASSPATH=%CLASSPATH%;c:\java\bin C:\Documents and Settings\Owner>echo %CLASSPATH% %CLASSPATH% C:\Documents and Settings\Owner> ------------- また、JAVAの入ってるフォルダは、 C:\JAVAで、ローカルディスクCの中です。 JAVAフォルダの中は、j2sdk-1_4_0-doc-jaフォルダと、J2SEフォルダ、 Janken.classがあります。 もう何が正しくて、何が誤りなのかもわかりません。 どうか、よろしくお願いいたします・・・・。

    • ベストアンサー
    • Java