1738725494
2025-02-05 00:12:00
この記事は雑誌で初めて公開されました プログラム!馬のシリアル#16。
Java Virtual Machine(JVM)は、Java(またはBytecode Javaでコンパイルされた他の言語)で書かれたプログラムがさまざまなオペレーティングシステムとハードウェアアーキテクチャで実行できる実行環境です。
JVMは、最初から動的になるように設計されています。ホットコードを読み込んでコンパイルに存在しないコードを実行できます。また、ネイティブの書店を呼び出すことができ、多くの監視機能をサポートします。
Javaコードから、反射APIのおかげでJavaコードを動的に呼び出し、危険なクラスのおかげでJavaメモリ割り当てメカニズムを超えてメモリアクセスを行うこともできます。
これらすべての機能により、JVMはビジネスアプリケーション開発のための選択プラットフォームの1つになりました。
しかし、その創造以来、セキュリティの原則が進化し、アプリケーションの安全性に固有のリスク、およびその影響がますます大きくなっているため、JVMは成功した機能を維持しながらリスクへの曝露の表面を制限するために進化しなければなりませんでした。これらの変更は、少なくともJava 9とJVMのモジュール化以来、非常に長い間開始されてきましたが、Global ReflectionがJava Enhancement Proposition(JEP)の場所を見たのはごく最近のことです。 デフォルトの整合性 まだドラフトにあります: JEPドラフト:デフォルトでの整合性。このJEPは、デフォルトの整合性が何であるかを定義し、その理由を説明し、参加するJEPSをリストします。それは他の多くのJEPを結びつける傘のJEPです。
デフォルトの整合性とは何ですか?
これがJEPの言うことです:
コンピュータープログラムのコンテキストでは、整合性とは、プログラムの構成要素とプログラム自体が全体で有効であることを意味します。
この背後には、非常に単純な原則があります。JVMの仕様は、プログラムを有効にするために必要なものを正確に説明する必要があり、その実装はそれに従わなければなりません。たとえば、テーブルの仕様は、テーブルが作成されたときに定義された制限内でのみアクセスできることを定義しています。この制約はJVMによって保証されており、違反が発生した場合に例外が解除されます。
整合性の利点は次のとおりです。
- コードは予測可能です。変数は常に使用される前に定義された値を持ち、データ操作は常に有効です。
- メモリは安全な方法で管理されます。メモリ管理が不十分なためのクラッシュのリスクが最小限に抑えられます。
- マルチスレッドプログラムは安定しています。オブジェクトは、マルチタスク環境であっても、一貫した状態を保持します。
l ‘カプセル化 JVMの完全性を可能にする基本原則の1つです。
カプセル化は、単一のエンティティ、一般にクラスでそれらを操作するデータと方法のグループ化で構成されています。これにより、外部アクセスデータと不正な変更を保護し、適切に定義されたインターフェイスを介してのみ処理できるようにします。
カプセル化は、プログラムの正確性、保守性、スケーラビリティ、セキュリティ、パフォーマンスなど、多くの利点をもたらします。
JVMの完全性に直接リンクしている人々にこだわりましょう。
- エグゼクティブ:カプセル化により、データが制御された方法でアクセスおよび変更されるようになり、エッジ効果と予期しないエラーが防止されます。
- 安全:データアクセスを制限することにより、カプセル化は不正なアクセスから機密情報を保護することに貢献します。
それにもかかわらず、Java開発キット(JDK)には、カプセル化をバイパスできるAPIがあります。
- AccessibleObject :: setAccessible(boolean) :この方法により、深い反射が可能になり、通常はアクセスできない場合でも、プライベートフィールドとメソッドへのアクセスが可能になります。
- sun.misc.unsafe :このクラスは、最終フィールドだけでなく、プライベートな方法やフィールドにアクセスする方法を提供します。
- Javaネイティブインターフェイス(JNI) :JNIでは、ネイティブコードがカプセル化の制限を尊重せずにJavaオブジェクトと対話することができます。
- 計装API :このAPIにより、エージェントはメソッドのバイトコードを変更し、カプセル化をバイパスできます。
したがって、JVMのデフォルトの整合性は、これらのAPIの動作をデフォルトで制限する必要があります。アイデアは、それらを削除するのではなく、それらの範囲を削減したり、開発者に使用を制御するために故意に許可するように強制することです。
深い反射を制限します
Java 9以来、モジュール性の導入(261を与える:システムモジュール)、Javaモジュールを使用して深い反射を制限することが可能です。 AccessibleObject::setAccessible(boolean) モジュールの制限を尊重します。モジュールのクラスは、別のモジュールのクラスのフィールドのアクセシビリティを変更できません。
Java 9で開始され、JDKのモジュール性が徐々に実装されたこの変更は、アプリケーションの開始時の警告の問題を介して最初に不正アクセスが落胆し、その後Java 16で禁止されました。--illegal-access=permit)モジュールの開口部を介したケース – ケースベース(--add-opens)。
安全でないものの使用を返します
クラス sun.misc.Unsafe 安全制御なしでさまざまな低レベル操作を実行する方法が含まれています。
安全でないコンポーネントは、JVMの完全性を損なうものです。
UnsafeはJavaアプリケーションではめったに使用されませんが、多くのフレームワークは彼と多くのJavaエージェントに基づいています。
長年にわたり、サポートされているAPIを介した多くの代替品が出現しているため、安全でないことの使用はますます必要です。
ヒープ内の低レベルのオブジェクトを処理することは、APIを介してより安全に実行できるようになりました varhandle、そしてヒープの外側のメモリでのデータの操作は、APIを介してより安全な方法で実行できるようになりました メモリセグメント。
Java 23以来 JEP 471:sun.misc.unsafeのメモリアクセスメソッドを除去のために非難する、安全でないメモリアクセス方法は減価償却されますが、それらの使用は常に許可されています。コマンドラインオプションを介して使用を制限することが可能です。 --sun-misc-unsafe-memory-access。
これらのメソッドの使用は、Javaの次のバージョンで徐々に制限されます。 Java 24から、彼らは最初の使用中にJVMのログに警告を発します。
JNIの使用を制限します
Java 24と JEP 472:JNIの使用を制限する準備をします、ネイティブの書店へのアクセスは、JNIと新しい外国機能およびメモリAPI(FFM)の両方で制限されます。
これは、Java 22以来のFFM APIの場合にすでに当てはまりました。
ネイティブの書店は、JVMの完全性を尊重しません。
- JVMクラッシュを引き起こす可能性のある可能性のある動作(未定義の動作)を持つこと。
- バイトバッファーを介して直接データを交換します。
- アクセス制御のないフィールドとメソッドにアクセスします。
- JVM関数を正しく呼び出します。
ネイティブの書店へのアクセスを許可するには、コマンドラインオプションを使用する必要があります --enable-native-access またはマニフェストの属性 Enable-Native-Access モジュールの名前または ALL-UNNAMED すべてのクラススコードを承認する。
現時点では、許可されていないJNI書店の使用は、アプリケーションを起動するために警告を発しますが、次のバージョンのJavaで使用されます。
計装APIの使用を制限します
エージェントは、実行中にアプリケーションのコードを変更できるコンポーネントです。
したがって、彼は多くの点でJVMの完全性を妥協することができます。
Java 21以来 JEP451:エージェントの動的な負荷を禁止する準備をする、エージェントJavaの動的負荷が制限されています。
コマンドラインオプション -XX:+DisableAttachMechanism エージェントの動的荷重を制御できるようにするため、現在はデフォルトで真実です。
現時点では、許可されていないJavaエージェントの動的荷重は、アプリケーションを起動するために警告を発しますが、Javaの次のバージョンでは徐々に制限されます。その後、コマンドラインオプションを介してJVMを起動するときにすべてのJavaエージェントを宣言する必要があります --agent。
結論
アプリケーションの安全性はますます重要であり、デフォルトでJavaがより多くのセキュリティを求めて進化していることは良いことです。また、これにより、どの書店またはモジュールがどのようなアクション(反射、ネイティブの書店の読み込みなど)を達成できるかをより適切に習得できる開発者の手により多くの力を置きます。
同様の記事
#JavaJVMのデフォルトの整合性に向けて