[Java] What is java escape parsing

2 minute read

Foreword

I’m touching Graal and I didn’t really understand what partial escape analysis was, so I checked it out.

↓ Articles about Graal and GraalVM https://qiita.com/kinshotomoya/items/39a821dd6a6a52202c0a

The sample code is written in scala.

What is escape

The object reference exists outside the method or in a different thread. By escaping, the object can be referenced from many unspecified places.

Escape condition

When does the actual code say that an object is escaped? There are mainly the following three conditions.

  1. Specify in method argument
  2. Return with return (specify as return value)

1. Specified in method argument

Reference to a which is an instance of Object can be referred beyond hoge method. Can also be referenced from the foo method

case class Object()

object Test {
  def hoge: Object = {
    val a = Object()
    foo(a)
  }
  
  def foo(obj: Object) = ???
}

2. Return with return (specify as return value)

Reference to instance b of Object can be referred beyond hoge method. The b2 variable has a reference to object a.

case class Object()

object Test {
  def hoge: Object = {
    val b = Object()
    b
  }
  
  val b2 = hoge()
}

In other words, it is possible to refer to the instance a, b of the above example beyond the method.

What is escape analysis?

Analyze whether the instance reference escapes outside the method or in another thread. There are various algorithms.

What if it’s parsed without being escaped?

If the result of escape analysis shows that the reference is closed in the method,

1. Store the instance in the stack instead of the heap.

If the instance is used only in the method, it is effective to store it in the stack area that is released after the method ends.

2. Ignore unnecessary synchronization when executing the method

If the reference is made only from a single thread, synchronization between threads becomes unnecessary.

Optimization example

As a result of escape analysis, the compiler optimizes the code. An example is shown below.

Inline

Here is the code:


class Person {
  def get(name: String) = {
    val person: Person = Person(name)
    if (person.name === "hoge") {
    }
    ...
  }
}

case class Person(name: String)

Person, which is an instance of Person object, is not escaped. In such cases, the compiler will optimize by inlining.

class Person {
  def get(name: String) = {
    // val person: Person = Person(name)
    if (name === "hoge") {// inline

    }
    ...
  }
}

case class Person(name: String)


Partial escape analysis

This is one of the features of the new JIT compiler Graal. It can be partially optimized.

If you have code like this:

class Person {
  def get(name: String) = {
    val person: Person = Person(name)
    val cachePerson = Cache.get(name)
    if (cachePerson.isDefined) {
      cachePerson
    } else {
     addToCache(person)
     person
    }
  }
}

case class Person(name: String)

If cachePerson exists, object person is not escaped. The compiler parses it and changes it into the following code.


class Person {
  def get(name: String) = {
    val cachePerson = Cache.get(name)
    if (cachePerson.isDefined) {
      cachePerson
    } else {
    Val person: Person = Person(name)
    AddToCache(person)
      person
    }
  }
}

case class Person(name: String)

If you move val person: Person = Person(name) under else and cachePerson exists, you can eliminate the memory allocation to the heap area. Instead, it is stored in the stack area, which improves processing efficiency.

If cachePerson does not exist, person is escaped and stored in the heap area.

Reference

  • https://www.slideshare.net/jyukutyo/graal-in-graalvm-a-new-jit-compiler
  • https://docs.oracle.com/javase/jp/11/vm/java-hotspot-virtual-machine-performance-enhancements.html#GUID-6BD8FCB5-995B-4AE9-BFAA-B2C7DE2BA5CD
  • https://www.weblio.jp/wkpja/content/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%A7% A3%E6%9E%90_%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E8%A7%A3%E6%9E%90% E3%81%AE%E6%A6%82%E8%A6%81
  • https://gist.github.com/kawasima/32b8097163029d452553e4ae5b8e070b