web-dev-qa-db-ja.com

Java:Java.util.Preferencesの失敗

私のプログラムは、暗号化されたプロダクトキーデータをJava.util.Preferencesクラス(ユーザーではなくシステム設定)を使用してコンピューターに保存します。問題は、WindowsとLinuxの両方で(OSXでテストしていませんが、おそらく同じです)、Sudoまたは管理者権限でプログラムを実行しないと、例外または警告が発生しますデータの読み取りまたは保存を試みるたびに。

ユーザーに管理者権限でプログラムを実行することを明らかにするのは非現実的です。最適なのは、オペレーティングシステムがユーザーに許可を求めることです。

これは非常にばかげており、Preferencesの目的の半分を削除します。これはどのように修正できますか?

ここに必要なものの概要があります:システム設定を保存するために、オペレーティングシステムに許可を求めるプログラムが必要です。


ここにエラー情報があります

ノードが存在しないためにノードを読み取ろうとしたときのエラーは次のとおりです。

Mar 18, 2011 9:41:15 AM Java.util.prefs.WindowsPreferences <init>
WARNING: Could not create windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
Mar 18, 2011 9:41:15 AM Java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002.
Mar 18, 2011 9:41:15 AM Java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp at root 0x80000002. Windows RegOpenKey(...) returned error code 2.
Mar 18, 2011 9:41:15 AM Java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002.
Mar 18, 2011 9:41:15 AM Java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002. Windows RegOpenKey(...) returned error code 2.

そして、これは私がノードに書き込もうとすると何が起こるかです:

Mar 18, 2011 9:43:11 AM Java.util.prefs.WindowsPreferences WindowsRegOpenKey1
WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002.
Mar 18, 2011 9:43:11 AM Java.util.prefs.WindowsPreferences openKey
WARNING: Could not open windows registry node Software\JavaSoft\Prefs\myapp\subpackage at root 0x80000002. Windows RegOpenKey(...) returned error code 2.
65
Jonah

残念ながら、ここで得た答えのほとんどは間違っています...少なくともわずかです。症状が治療されているという意味で、原因ではありません。

要約しましょう。 Java Preferencesには、2つの「ツリー」があります: ユーザーツリーシステムツリー 。 Java Preferences(バッキングストアと呼ばれます)に独自のバックエンドを記述できますが、開発者はほとんどいないため、JDKのデフォルトバッキングストアになります。 Windowsプラットフォームでは、これはWinレジストリ、具体的には次のことを意味します。

  • ユーザーツリーHKEY_CURRENT_USER\Software\JavaSoft\Prefsに書き込まれます(OSユーザーalwaysはここに書き込みアクセス権があります)
  • システムツリーHKEY_LOCAL_MACHINE\Software\JavaSoft\Prefsに書き込まれます(管理権限を持つOSユーザーのみがここに書き込みアクセスできます)

要約すると、コードがシステムツリーを使用しようとしない限り、問題はなく、OSレベルでの特権の割り当てを台無しにする必要はありません。システムツリーは「ホスト上のすべてのユーザー」を対象とし、ユーザーツリーは特定のログインユーザーを対象としています。あなたの場合、私はあなたがユーザーツリーで十分であると確信しているので、それは本当にあなたの解決策です。特権をいじったり、管理者として実行したりしないでください。

....しかし、もっとあります。指示に従って、コードがJava Preferencesシステムツリーに意図的に触れていないとします。その後、still Windowsで次の警告が表示されます。

WARNING [Java.util.prefs]: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.

それで何が起こっているのでしょうか?私はあなたに間違ったアドバイスをしましたか?あんまり。私と一緒にいて。

JDKソースコードに目を向けると、0x80000002はHKLM、つまり触れてはならないWinレジストリ内の場所を意味することがわかります。コードがシステムツリーを参照することはありませんが、まだこの警告が表示されます!?? (この時点で、あなたはすべての髪を引き抜かなければなりません...私がしたように)

まあ、これは実際に JDKバグ があるまれな機会の1つです。詳細については この回答 を参照してください。微妙なバグが何年もJDKで検出されない理由に興味がある場合は、お読みください。このバグはJDK 1.4以来存在していましたが、最近修正されたばかりで、まだJDK 8にバックポートされていません。

最高のアドバイス

  • コードがシステムツリーではなく、ユーザーツリーのみを参照していることを確認してください。 OSがシステム全体の場所に書き込むためにすべての種類の特権を必要とするのは公正です。 本当にそのような場所に書き込む必要がある場合、特権を割り当てるか、管理者として実行するかしないか以外に解決策はありません。
  • 警告を無視します。 Java 9に到達するか、Oracleがバグ修正をJava 8にバックポートすることを決定すると、それはなくなります。警告は無視しても問題ありません。
  • または、プログラムで警告を無視してみてください。それはJDKのPlatform Loggerから来ているので、私は自分で試したことはありませんが、次のようなものが機能するはずです。

    Sun.util.logging.PlatformLogger platformLogger = PlatformLogger.getLogger("Java.util.prefs");
    platformLogger.setLevel(PlatformLogger.Level.OFF);
    
42
peterh

この リンク は私のために働いています:

問題の解決回避策は、administratorとしてログインし、HKEY_LOCAL_MACHINE\Software\JavaSoft\Prefsキーを作成することです。

42
morrxy

レジストリエントリのアクセス権を変更することができます。 HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefsへのフルアクセス権を全員に許可すると、全員に同じ設定が表示され、誰でもグローバルに変更できるようになります。これは、お客様がインストールするソフトウェアのソリューションではないことは承知していますが、誰かに役立つかもしれません。

11
kuester2000

フィードバックに基づいて回答を変更します。このソリューションはおそらく過剰ですが、...

  • レジストリの代わりにファイルに書き込むようにストアを変更することをお勧めします( example
  • 多くのJavaベースの製品には、独自のJVMが付属しています。カスタムポリシーファイル(一般的な場所に書き込むために必要な場合)で実行し、サポートの問題(古い/未テストのJVMが使用されているなど)を節約できるようにするため
5
qwerty

特にWindows 7では、Java.util.prefs.preferencesのバッキングストアがMS-Windowsの下にあるWindowsレジストリへの書き込み権限がデフォルトでJVMにありません。

ReverseXSLトランスフォーマーまたはRegexテスタープログラムのいずれかを実行すると、次のようなエラーが発生する可能性があります。 Windows RegCreateKeyEx

これにより、ライセンスを登録できなくなります。ソフトウェアがフリーソフトウェアモードで変換を実行することを妨げません。

この問題の修正は、問題のレジストリルートキーに必要な権限を付与するだけです。

管理者としてregedit.exeを実行します(regedit.exeはc:\ Windowsオペレーティングシステムのルートディレクトリにあります)。キーHKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Prefsに移動します。右クリックして権限を設定します。 reverseXSLソフトウェアを実行する必要があるユーザーの[フルコントロール]チェックボックスをオンにします。

3
guest

管理者としてアプリケーションを実行するか、Eclipseを使用している場合は管理者としてEclipseを実行します。

1
Ashu

これは、2019年1月にJava SE Development Kit 8u202で修正されました。

これは、クリティカルパッチアップデート(CPU)8u201とは対照的に、パッチセットアップデート(PSU)です。違いは ここ で説明されています。 (このページでは、例としてJava 7を使用していますが、ポイントを取得しています。)

ダウンロードは、「Java SE Development Kit 8」ページの下にあります。 ( https://www.Oracle.com/technetwork/Java/javase/downloads/jdk8-downloads-2133151.html

1
Katrina Eaton

The Answer by peterh すでに背景について詳しく説明しましたが、修正を探していて見つけました!

PlatformLogger自体に触れることはできないため、そのメッセージを無効にする必要があります。

// get rid of the bugged Preferences warning
PrintStream err = System.err;
System.setErr(new PrintStream(new OutputStream() {
    public void write(int b) {}
}));
Preferences PREFS = Preferences.userNodeForPackage(Settings.class);
System.setErr(err);

このようにして、迷惑な警告は痕跡を残さずに消えます。これは、プログラムで初めてPreferences APIを参照する時点でのみ行う必要があることに注意してください。

1
Xerus

私にとっての解決策は明らかではありませんでした-それはキーの長さの制限のように見えるため、Oracleから暗号化セキュリティjarを更新することでした(試してみるまで、関連しているとは思わなかった)。

Oracle Webサイトからダウンロード

ダウンロードには手順と説明が含まれています。

一部の国の輸入管理規制により、Java Runtime Environment、またはJRE(TM)、8環境にバンドルされているJCEポリシーファイルのバージョンでは、「強力な」が制限された暗号化が許可されますこのダウンロードバンドル(このREADMEファイルを含むもの)は、暗号強度に制限のない「無制限の強度」ポリシーファイルを提供します。

これは明らかにレジストリキーにも適用されます

0
Nick Cardoso

修正方法は、管理者としてJMeterを実行することです。レジストリキーが作成されます。通常のユーザーとしてJMeterを再起動すると、警告は表示されなくなります。 JMeter公式サイト-変更

0
Arun Girdhar