JVMをどのようにクラッシュさせますか?


144

プログラミングスキルについての本を読んでいて、著者がインタビュー対象者に「JVMをクラッシュさせるにはどうすればよいですか」と尋ねました。最終的にすべてのメモリを使い果たす無限のforループを作成することで、そうすることができると思いました。

誰かが何か考えを持っていますか?



stackoverflow.com/questions/30072883/…「JDK1.8_40以降(OracleまたはOpenJDKでも同じ)を使用している場合、次のコードとダイアログのサイズ変更により、アプリケーションがクラッシュします(Windows 7、x64、64ビットJDKを試しました)」 -コードはわずか40行で、JVMが適切にクラッシュします。
Dreamspace社長、2016

回答:


6

単一の「答え」に最も近いのはSystem.exit()、適切なクリーンアップなしでJVMを即座に終了させることです。しかし、それとは別に、ネイティブコードとリソースの枯渇が最も可能性の高い答えです。または、Sunのバグトラッカーを調べて、ご使用のバージョンのJVMのバグを探すこともできます。その一部は、繰り返し発生するクラッシュシナリオを可能にします。以前は、32ビットバージョンで4 Gbのメモリ制限に近づくと、半定期的なクラッシュが発生していました(現在は通常64ビットを使用しています)。


71
適切なクリーンアップなしで?本気ですか?ドキュメントは、「シャットダウンシーケンスを開始することにより、現在実行中のJava仮想マシンを終了します...登録されているすべてのシャットダウンフック(ある場合)が開始されます...呼び出されていないファイナライザがすべて実行されます」-それは適切なクリーンアップではありませんか?
user85421 2009

51
これはJVMをクラッシュさせるものではなく、意図的かつ明示的に、実行の正常なシャットダウンを開始します。
BenM 2010年

9
jvmのクラッシュにより近いのは、Runtime.getRuntime()。halt(status)です。ドキュメントによると、「このメソッドはシャットダウンフックを開始せず、終了時のファイナライズが有効になっている場合、呼び出されていないファイナライザを実行しません」。まだクラッシュではありませんが、System.exitよりは近いです。
ヘンリー2012

48
これは本当に悪い答えです。
Antonio

174

OutOfMemoryErrorやStackOverflowErrorをスローすることをクラッシュとは呼びません。これらは通常の例外です。VMを実際にクラッシュさせるには、3つの方法があります。

  1. JNIを使​​用し、ネイティブコードでクラッシュします。
  2. セキュリティマネージャーがインストールされていない場合は、リフレクションを使用してVMをクラッシュさせることができます。これはVM固有ですが、通常、VMはネイティブリソースへの一連のポインタをプライベートフィールドに格納します(たとえば、ネイティブスレッドオブジェクトへのポインタはjava.lang.Threadのロングフィールドに格納されます)。リフレクションを介してそれらを変更するだけで、VMは遅かれ早かれクラッシュします。
  3. すべてのVMにバグがあるため、1つをトリガーする必要があります。

最後の方法として、Sun Hotspot VMを静かにクラッシュさせる短い例があります。

public class Crash {
    public static void main(String[] args) {
        Object[] o = null;

        while (true) {
            o = new Object[] {o};
        }
    }
}

これにより、GCでスタックオーバーフローが発生するため、StackOverflowErrorは発生せず、hs_err *ファイルを含む実際のクラッシュが発生します。


9
うわー!これにより、Sun Java 5、Sun Java 6、およびOpenJDK 6(Ubuntu 9.04上)がクラッシュします。hs_err*ファイルはなく、「セグメンテーション違反」のみです。...
ヨアヒムザウアー

1
System.exit()は、JVMをクラッシュさせるはるかに簡単な方法です(セキュリティマネージャがインストールされていない場合)
instantsetsuna

4
いつ修正されたかはわかりませんが、1.7.0_09でテストしただけで問題ありません。ちょうど期待通りになりました:スレッド "main"の例外java.lang.OutOfMemoryError:CrashJVM.main(CrashJVM.java:7)のJavaヒープ領域
Chad NB

2
上記のコードをIntel Core i7 2.4 GHz / 8 GB RAM / JDK1.7 64ビットで試しましたが、JVMは20分後もまだアップしています。(面白い:私のラップトップのファンは空の戦闘機よりも大きかった)。この問題はJDK 1.7以降で修正されましたか?
realPK 2014

3
JDK 1.8_u71では、これが原因でjava.lang.OutOfMemoryError: GC overhead limit exceeded
Clashsoft


56

これを使って:

import sun.misc.Unsafe;

public class Crash {
    private static final Unsafe unsafe = Unsafe.getUnsafe();
    public static void crash() {
        unsafe.putAddress(0, 0);
    }
    public static void main(String[] args) {
        crash();
    }
}

このクラスは信頼できるコードを使用しているため、ブートクラスパス上にある必要があるため、次のように実行します。

java -Xbootclasspath / p:。クラッシュ


14
-Xbootclasspathを使用する代わりに、これを行うこともできField f = Unsafe.class.getDeclaredField( "theUnsafe" ); f.setAccessible( true ); unsafe = (Unsafe) f.get( null );ます。
強引な2014

Unsafe定義により、「安全でない」です。これは少しごまかしです。
ホットリックス

1
getDeclaredFieldLinux x64上のJDK 8u131でのトリックを使用した動作を確認しましhs_err_pid*.logSIGSEGV
Jesse Glick 2017

使用Unsafeはチートではありません。OPはプログラミングの問題に対する「クリーン」な解決策を探していません。最悪の方法でクラッシュするには、jvmが必要です。厄介なネイティブのことを行うことがそれを可能にするものであり、まさにそれが行うことUnsafeです。
jvdneste 2017

34

情熱的なプログラマーでもこの質問に出くわしたので、ここに来ましたChad Fowlerによる。コピーにアクセスできない人のために、質問は「本当に優れたJavaプログラマー」を必要とする職位について面接する候補者に対する一種のフィルター/テストとして構成されています。

具体的には、彼は尋ねます:

純粋なJavaで、Java仮想マシンをクラッシュさせるプログラムをどのように作成しますか?

15年以上Javaでプログラミングしてきましたが、この質問は不可解で不公平であることがわかりました。他の人が指摘したように、マネージ言語としてのJavaは、クラッシュしないように特別に設計されてます。もちろん、JVMのバグは常にありますが、

  1. 15年以上のプロダクションレベルのJREの後、それはまれです。
  2. そのようなバグは次のリリースでパッチが適用される可能性が高いので、プログラマーとして、現在のJREショーストッパーのセットに遭遇して詳細を思い出す可能性はどれくらいありますか?

他の人が述べたように、JNIを介したいくつかのネイティブコードは、JREをクラッシュさせる確実な方法です。しかし、著者は特に純粋なJavaで言及しているので、それは終わりです。

別のオプションは、JREの偽のバイトコードをフィードすることです。ガベージバイナリデータを.classファイルにダンプし、JREに実行するよう依頼するのは簡単です。

$ echo 'crap crap crap' > crap.class
$ java crap
Exception in thread "main" java.lang.ClassFormatError: Incompatible magic value 1668440432 in class file crap

それは重要ですか?つまり、JRE自体はクラッシュしていません。偽のコードを適切に検出して報告し、終了しました。

これにより、再帰によってスタックをブローする、オブジェクトの割り当てによってヒープメモリが不足する、単純にをスローするなど、最も明白な種類のソリューションが残りますRuntimeException。ただし、これによってJREが終了するStackOverflowErrorか、同様の例外が発生しますが、これも実際にはクラッシュではありません

だから何が残っていますか?筆者が適切な解決策として本当に心に留めていたことを聞きたいです。

更新:Chad Fowler がここで応答しました

PS:それは他の点では素晴らしい本です。Rubyを学びながら、道徳的なサポートを得るためにそれを手に入れました。


1
このようなインタビューの質問は、Java開発者が1)(多くの)JVMクラッシュを目撃し、2)結論を導き出している、あるいは(自称)Javaの専門家がクラッシュの根本的な理由。チャド・ファウラー氏はまた、自称Javaプログラマーは「間違った答えを思い付くことすらできなかった」、つまり、潜在的な問題のクラス全体についていつまで考えたことがなかったかについても述べています。結論:この質問は、「JVMのクラッシュを防ぐ方法」へのsegwayです。これは明らかに知っておくと良いでしょう。
ションジラ

1
JVMや「クラッシュ」という言葉を実際に理解していないため、「スタックのオーバーフロー」、system.exit()、またはその他の「通常の」シャットダウン(ほとんどの場合はそうです)とだけ答える人を探します。(あなたがしたように)これが非常に異常であることを認識することは、より高度なプログラマを特定するためのかなり良い方法です。私はあなたの最初の発言に同意します。質問するか、質問されるのは非常に優れた完全に公正な質問だと思います。具体的な答えのないものが常に最善です。
Bill K

20

このコードは厄介な方法でJVMをクラッシュさせます

import sun.dc.pr.PathDasher; 

public class Crash
{
     public static void main(String[] args)
     {    
        PathDasher dasher = new PathDasher(null) ;
     }
}

1
このコードでJDK 1.7を使用するとコンパイルエラーが発生する: アクセス制限:必要なライブラリC:\ Program Files \ Java \ jdk1.7.0_51 \ jre \ lib \ rt.jarの制限のため、タイプPathDasherにアクセスできません
realPK

7
これInternalErrorはJDK 1.8でスローされます。JVMは失敗しなくなりました。
Sotirios Delimanolis 2014

18

私がこれを試した最後の時間はそれをするでしょう:

public class Recur {
    public static void main(String[] argv) {
        try {
            recur();
        }
        catch (Error e) {
            System.out.println(e.toString());
        }
        System.out.println("Ended normally");
    }
    static void recur() {
        Object[] o = null;
        try {
            while(true) {
                Object[] newO = new Object[1];
                newO[0] = o;
                o = newO;
            }
        }
        finally {
            recur();
        }
    }
}

生成されたログファイルの最初の部分:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x000000006dad5c3d, pid=6752, tid=1996
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (11.2-b01 mixed mode windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x2e5c3d]
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

---------------  T H R E A D  ---------------

Current thread (0x00000000014c6000):  VMThread [stack: 0x0000000049810000,0x0000000049910000] [id=1996]

siginfo: ExceptionCode=0xc00000fd, ExceptionInformation=0x0000000000000001 0x0000000049813fe8 

Registers:
EAX=0x000000006dc83090, EBX=0x000000003680f400, ECX=0x0000000005d40ce8, EDX=0x000000003680f400
ESP=0x0000000049813ff0, EBP=0x00000000013f2df0, ESI=0x00000000013f0e40, EDI=0x000000003680f400
EIP=0x000000006dad5c3d, EFLAGS=0x0000000000010206

純粋にJavaコードでそれを行う方法を示す唯一の2つの回答の1つであり、完全なコードが含まれていることを考えると、私は反対投票で少し面白がっています。
ホットリックス2015年

反対票は不当であることに同意します-これは本当のクラッシュですが、インタビューの質問にどのように答えますか?以前にこれを調査して記憶していなかった場合を除いて、インタビューで回答としてそれを与えることはできません。もし私がとにかく中立から貧弱な回答を検討したい場合は、問題への取り組み方を示していません。私はあなたがjvmバグエクスプロイトについてグーグルだったことを期待し、優れた答えであるものを実装します。
Bill K

@BillK-いいえ、上記は完全に私自身の作品ですが、数年前にさまざまなことを実験して思いつきました。インタビューでは、おそらく「try / catchと再帰を使用してそれを実行しましたが、今のところ正確なコードを確認することはできません。」
Hot Licks

1
詳細(JDKバージョン、VM引数)は何ですか?「11.2-b0」のバージョンがわからない。これを実行していますが、CPUを大量に消費するだけです。
Stefan Reich

@Hot Licks:JVMクラッシュの例のコンセプトは何ですか?JVMがコードについてクラッシュする理由。すべてのスレッドに個別のスタックスレッドがあります...
VJS

15

完璧なJVM実装は決してクラッシュしません。

JVMをクラッシュさせるには、JNI以外に、VM自体のバグを見つける必要があります。無限ループはCPUを消費するだけです。メモリを無限に割り当てると、適切に構築されたJVMでOutOfMemoryErrorが発生するだけです。これは他のスレッドで問題を引き起こす可能性がありますが、優れたJVMはクラッシュしません。

VMのソースコードにバグが見つかり、VMの実装のメモリ使用量にセグメンテーション違反が発生した場合などは、実際にクラッシュする可能性があります。


14

JVMをクラッシュさせたい場合-Sun JDK 1.6_23以下で以下を使用します。

Double.parseDouble("2.2250738585072012e-308");

これは、Sun JDKのバグが原因です-OpenJDKにもあります。これは、Oracle JDK 1.6_24以降で修正されています。


10

クラッシュの意味によって異なります。

無限の再帰を実行してスタック領域を使い果たすことができますが、「正常に」クラッシュします。例外が発生しますが、JVM自体がすべてを処理します。

JNIを使​​用してネイティブコードを呼び出すこともできます。正しく実行しないと、クラッシュする可能性があります。これらのクラッシュのデバッグは「楽しい」です(信頼してください。署名されたJavaアプレットから呼び出す大きなC ++ DLLを作成する必要がありました)。:)


6

Jon Meyer 著のJava Virtual Machineには、JVMをコアダンプさせる一連のバイトコード命令の例が含まれています。この本のコピーが見つかりません。誰かが持っている場合は、それを調べて回答を投稿してください。


5

winxpsp2 w / wmp10 jre6.0_7

Desktop.open(uriToAviOrMpgFile)

これにより、生成されたスレッドがキャッチされていないThrowableをスローし、ホットスポットをクラッシュさせます

YMMV


5

ハードウェアが壊れると、プログラムがクラッシュする可能性があります。私はかつて、特定のマシン上で再現可能な方法でアプリをクラッシュさせたが、まったく同じ設定で他のマシン上で問題なく動作した。マシンに欠陥のあるRAMがあったことがわかりました。


5

最短の方法:)

public class Crash
{
    public static void main(String[] args)
    {
        main(args);
    }
}

クラッシュしません。コンパイル時エラーが発生しますException in thread "main" java.lang.StackOverflowError at Test.main。私はjdk1.8.0_65を使用しています
Quazi Irfan

5

クラッシュではないが、使用の受け入れられた答えよりもクラッシュに近い System.exit

呼び出すことでJVMを停止できます

Runtime.getRuntime().halt( status )

ドキュメントによると:-

「このメソッドでは、終了フックが有効になっている場合、シャットダウンフックが開始されず、呼び出されていないファイナライザーが実行されません。」



4

あなたがあなたがメモリを使い果たしたふりをしたいなら、あなたはすることができます

public static void main(String[] args) {
    throw new OutOfmemoryError();
}

ネイティブメソッド(組み込みのメソッド)を呼び出してJVMにエラーファイルをダンプさせるいくつかの方法を知っていますが、これを行う方法がわからないのがおそらく最善です。;)


4

処理できない状況(つまり、Java例外またはエラーがない)のためにプロセスの異常終了としてクラッシュを定義した場合、これはJava内から実行できません(sun.misc.Unsafeクラスを使用する権限がない場合)。これがマネージコードの要点です。

ネイティブコードでの通常のクラッシュは、間違ったメモリ領域(nullアドレスまたはミスアライメント)へのポインタを逆参照することで発生します。別の原因としては、不正な機械命令(オペコード)や、ライブラリまたはカーネルコールからの未処理の信号が考えられます。JVMまたはシステムライブラリにバグがある場合、どちらもトリガーできます。

たとえば、JITされた(生成された)コード、ネイティブメソッド、またはシステムコール(グラフィックスドライバー)は、実際のクラッシュにつながる問題を抱えている可能性があります(ZIP関数を使用していてメモリが不足すると、クラッシュが発生することはよくありました)。これらの場合、JVMのクラッシュハンドラーが起動し、状態をダンプします。また、OSコアファイル(Windowsではワトソン博士、* nixではコアダンプ)を生成することもできます。

Linux / Unixでは、実行中のプロセスにシグナルを送信することにより、JVMを簡単にクラッシュさせることができます。注:SIGSEGVHotspotがこの信号をキャッチし、ほとんどの場所でNullPointerExceptionとして再度スローするため、これを使用しないでください。したがってSIGBUS、たとえばを送信することをお勧めします。


3

JNIはクラッシュの大きな原因です。JVMTIインターフェースもC / C ++で作成する必要があるため、JVMTIインターフェースを使用してクラッシュする可能性もあります。


2

より多くのスレッドを生成するスレッドプロセス(より多くのスレッドを生成する...)を作成すると、最終的にはJVM自体でスタックオーバーフローエラーが発生します。

public class Crash {
    public static void main(String[] args) {

        Runnable[] arr = new Runnable[1];
        arr[0] = () -> {

            while (true) {
                new Thread(arr[0]).start();
            }
        };

        arr[0].run();
    }
}

これは私に出力を与えました(5分後、あなたのラムを見てください)

An unrecoverable stack overflow has occurred.
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_STACK_OVERFLOW (0xc00000fd) at pc=0x0000000070e53ed7, pid=12840, tid=0x0000000000101078
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# 

1

「クラッシュ」とは、JVM がhs_err_pid%p.log書き出されるなど、JVMの突然の中止を意味する場合は、この方法で実行できます。

-Xmx argを小さな値に設定し、メモリ不足で強制的にクラッシュするようにJVMに指示します。

 -Xmx10m -XX:+CrashOnOutOfMemoryError

明確にするために、上記の2番目の引数がないと、jvm がOutOfMemoryErrorで終了するだけですが、「クラッシュ」したり、jvmを突然中止したりすることはありません。

この手法は、JVM -XX:ErrorFile引数をテストしようとしたときに役立ちました。これは、このようなhs_err_pidログを書き込む場所を制御します。そのようなクラッシュを強制する方法を見つけようとしているときに、私はこの投稿をここで見つけました。上記が私のニーズに最も簡単に機能することが後でわかったとき、私はそれをここのリストに追加したいと思いました。

最後に、FWIW、argsに-Xms値が(上記よりも大きい値に)設定されているときに誰かがこれをテストする可能性がある場合は、それも削除または変更する必要があります。そうしないと、クラッシュは発生しませんが、単純にjvmの起動に失敗し、「初期ヒープサイズが最大ヒープサイズより大きい値に設定されています」と報告されます。(JVMを一部のアプリサーバーなどでサービスとして実行している場合、それは明らかではありません。繰り返しますが、私はそれを私に噛み付けたので、共有したいと思いました。)


0

その無限forループを同じ関数への再帰呼び出しに変更すると、スタックオーバーフロー例外が発生します。

public static void main(String[] args) {
    causeStackOverflow();
}

public void causeStackOverflow() {
    causeStackOverflow();
}

0

私は今それをやっていますが、方法は完全にはわかりません... :-) JVM(と私のアプリ)が完全に消えることがあります。エラーはスローされず、何も記録されません。警告なしで、すぐに作業状態からまったく実行されない状態になります。


ハードウェア、特にメモリのチェックを開始します!
するThorbjörnRavnアンデルセン

残念ながら、他の方法では問題なく動作する複数のマシン上にあります。それを行うのはこの1つの特定のアプリだけです(そして、メモリやプロセッサを集中的に使用しません)。
Brian Knoblauch、

0

最短?Robotクラスを使用してCTRL + BREAKをトリガーします。コンソールを閉じずにプログラムを閉じようとしたときに、これを見つけました(「終了」機能はありませんでした)。


古い質問-うまくいけば、誰かがあなたの答えから将来利益を得るでしょう。
dbmitch 2016年

0

これは重要ですか?

long pid = ProcessHandle.current().pid();
try { Runtime.getRuntime().exec("kill -9 "+pid); } catch (Exception e) {}

LinuxおよびJava 9以降でのみ機能します。

何らかの理由でProcessHandle.current().destroyForcibly();、JVMを取得できず、JVMを強制終了せず、現在のプロセスの破棄が許可されていないjava.lang.IllegalStateExceptionというメッセージをスローします。


0

JVMクラッシュを複製しようとすると、この問題が発生します。

Jniは機能しますが、さまざまなプラットフォームに合わせて調整する必要があります。最終的に、私はこの組み合わせを使用してJVMをクラッシュさせます

  1. このJVMオプションでアプリケーションを起動します -XX:+CrashOnOutOfMemoryError
  2. a long[] l = new long[Integer.MAX_VALUE];を使用してOOMをトリガーする

その後、JVMがクラッシュし、クラッシュログが生成されます。


-2

「クラッシュ」がjvm /プログラムの正常終了を妨げる何かである場合、未処理の例外がこれを行う可能性があります。

public static void main(String args[]){
   int i = 1/0;
   System.out.print(i); // This part will not be executed due to above  unhandled exception
  }

だから、それはクラッシュの種類に依存します!?


3
例外のスローはクラッシュではありません。
Quazi Irfan 2016

これは、かかわらず、未処理の実行時例外は、クラッシュされArithmeticExceptionている
ミッド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.