Blog

JFR Event Streaming を利用して、ByteBuffer で OutOfMemoryError が起きたときに harakiri する。

import jdk.jfr.consumer.RecordedClass
import jdk.jfr.consumer.RecordedEvent
import jdk.jfr.consumer.RecordingStream
import java.nio.ByteBuffer
import java.time.Duration
import kotlin.system.exitProcess


fun main(args: Array<String>) {
    // OOME を発行させるスレッド
    Thread {
        Thread.sleep(1000)

        val bbList = mutableListOf<ByteBuffer>()
        while (true) {
            try {
                val bb = ByteBuffer.allocateDirect(Int.MAX_VALUE)
                bbList.add(bb)
            } catch (e: Error) {
                println("Caught $e")
            }
        }
    }.start()

    // OOME があったら harakiri する。
    RecordingStream().use { rs ->
        rs.enable("jdk.JavaExceptionThrow").withPeriod(Duration.ofSeconds(1))
        rs.onEvent("jdk.JavaExceptionThrow") { event: RecordedEvent ->
            val message = event.getString("message")
            val thrownClass = event.getValue<RecordedClass>("thrownClass")
            if (thrownClass.name == "java.lang.OutOfMemoryError" && message.startsWith("Cannot reserve")) {
                println("Caught OutOfMemoryError! $event")
                exitProcess(4)
            }
        }
        println("Starting RecordingStream")
        rs.start()
    }
}