6行でJavaをセグフォらせる

初投稿です。お見苦しいところもあると思いますが、ご了承ください。

pythonから各言語をセグフォらせるのが流行ってきたので...

[pythonを三行でセグフォらせる](https://qiita.com/autotaker1984/items/a8ba955acdc81c907b3d)
[pythonを2行でセグフォらせる](https://qiita.com/sh1ma/items/a6dd1bcca0d9725e7e67)
[C言語で16文字でセグフォらせる](https://qiita.com/yasuo-ozu/items/ddc5d3e8e4a97eaa470c)
[Pythonを33文字でセグフォらせる](https://qiita.com/kanimum/items/95a45d8be31ef75d4332)
[Rustを5行でセグフォらせる](https://qiita.com/YoshiTheChinchilla/items/b9f4a6e92266e8ec9d3d)
[C 言語で 5 文字でセグフォらせる](https://qiita.com/zk_phi/items/bd59111e677e6d0e5720)

# 実際のコード

無理に6行にした結果

```java:a.java
import java.lang.reflect.*;
import sun.misc.Unsafe;
class A {public static void main(String[] a) throws Exception {Constructor<Unsafe> b=Unsafe.class.getDeclaredConstructor();
    b.setAccessible(true);
    b.newInstance().putLong(0, 0);} }
```

無理やり過ぎで可読性が皆無です
コードを整理すると

```java:a.java
import java.lang.reflect.*;
import sun.misc.Unsafe;
class A {
    public static void main(String[] a) throws Exception{
        Constructor<Unsafe> b=Unsafe.class.getDeclaredConstructor();
        b.setAccessible(true);
        b.newInstance().putLong(0, 0);
    }
}
```

あまり変わりませんね...


## 実行結果

### Linux(Ubuntu)の場合
```bash:Ubuntu
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f8b7c08ba84, pid=1986, tid=1987 　#ここでセグフォ(アクセス違反)が起きている
#
# JRE version: OpenJDK Runtime Environment (14.0.1+7) (build 14.0.1+7-Ubuntu-1ubuntu1)
# Java VM: OpenJDK 64-Bit Server VM (14.0.1+7-Ubuntu-1ubuntu1, mixed mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# V  [libjvm.so+0xe99a84]
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/user/hs_err_pid1986.log
#
# If you would like to submit a bug report, please visit:
#   Unknown
#
Aborted
```
(Ubuntu+OpenJDK Runtime Environment 14.0.1)

WSL2で実行したため実際の結果とは異なる場合があるかもしれません。

実行すると禍々しいエラー文と750行近くのエラー文が生成されます。

エラー文の5行目に注目してすると...

```bash:4行目
SIGSEGV(0xb)atpc=0x00007f8b7c08ba84,pid=1986, tid=1987
```

とあるように`SIGSEGV`(アクセス違反)シグナルをを受け取ってますね


さらにlogファイルは呼び出されたファイルやメモリダンプが詳しく生成されます。

Ubuntuのlogファイル49行目:

```bash:has_err_pid{posess_id}.log
49:siginfo: si_signo: 11 (SIGSEGV), si_code: 1 (SEGV_MAPERR), si_addr: 0x0000000000000000
```
とあるようにアドレスの`0番地`にアクセスして`SEGV_MAPERR`(マッピングされてないメモリにアクセスしたときに起こるエラー）
が起こっていることが分かりますね


### Windowsの場合

```bash:Windows
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffd4fa119b7, pid=18520, tid=8224
#
# JRE version: Java(TM) SE Runtime Environment (14.0.1+7) (build 14.0.1+7)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (14.0.1+7, mixed mode, sharing, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x7219b7]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\User\aa\hs_err_pid18520.log
#
# If you would like to submit a bug report, please visit:
#   https://bugreport.java.com/bugreport/crash.jsp
#
```
(Windows + Java(TM) SE Runtime Environment 14.0.1)

先ほどのUbuntuと同じく禍々しいエラー文と共にclassファイルと同じディレクトリにログファイルが生成されます。

4行目に注目すると

```bash:4行目
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffd4fa119b7, pid=18520, tid=8224
```

`EXCEPTION_ACCESS_VIOLATION`(アクセス違反)が起きていることが分かりますね。
同じくclassファイルと同じディレクトリに生成されたlogファイルを覗いてみると


Windowsのlogファイルの40行目:

```bash:has_err_pid{prosess_id}.log
40:#siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), writing address 0x0000000000000000
```
メモリの`0番地`に`writing`(書き込み）してアクセス違反起こっていることが分かりますね。

##セグフォについて

なんだよ！`Segmentation Fault`エラーでてないやんけ！詐欺やん！って思ってる人もいると思いますが、

> "[wikipedia -セグメンテーション違反-](https://ja.wikipedia.org/wiki/%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%81%95%E5%8F%8D)"より

>>UNIXライクのオペレーティングシステム上では、不正なメモリにアクセスをするプロセスは`SIGSEGV`シグナルを受け取る。Microsoft Windows上では、不正なメモリにアクセスするプロセスは`STATUS_ACCESS_VIOLATION`例外を受け取る

とのことから私はセグフォとして扱っています。

# 超大雑把な解説
`sun.misc.Unsafe`でJavaでもメモリをアクセスする能力を手に入れれます。

じゃあ`Unsafe.getUnsafe().putLong(0, 0)`でもっと短くできんじゃないの？って思うかもしれませんが、

javaの`unsafe`は名前の通りものすごく安全ではないクラスです。
finalの値を変更したりメモリを確保したり、アクセスしたりやりたい放題できます（ある程度制限があるらしいが）
そのため、コンストラクタがprivateでさらに`getunsafe()`は`getclassloder()`がnullの場合しかインスタンスを生成できません。

その抜け道として、リフレクションAPIで無理やりインスタンス化、さらに`setAccessible(true)`を使って普通はアクセスできないメソッドにアクセスできるようにします。

最後に`putLong(address, x);`で`address`にメモリ番地、`x`に適当な値を入れることでjavaでもセグフォを引き寄せることができました!!やったね！



#参考にしたサイト等

[sun.misc.Unsafe の魔力](https://blog1.mammb.com/entry/2015/06/26/005020)
[何かの時にスッと使える力技 - Reflection 編](https://qiita.com/KeithYokoma/items/9e692808095acf560bc9)
[セグメンテーション違反-wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BB%E3%82%B0%E3%83%A1%E3%83%B3%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%81%95%E5%8F%8D)


編集リクエストなど気軽に送りつけてください。
拙い文章ですが最後まで閲覧いただきありがとうございました！