Search code examples
javabytecode

`obj.f(null)` in Java bytecode


Is it safe to assume that obj.f(null) is always compiled to 2 consecutive instructions

ACONST_NULL
INVOKEVIRTUAL <type-of-obj> f <descriptor-of-f>

by javac, no matter where obj.f(null) appears in source code and how it is intermingled with other source code?

EDIT: I don't intend to do nullability check. I don't care about Object a = null; obj.f(a);.


EDIT: @OliverCharlesworth asked for my original problem. I want to detect obj.f(null) in bytecode with asm library. One can easily think of 2 ways of solving this problem.

  1. Use AnalyzerAdapter to verify whether the last element in stack is of type NULL when interested INVOKEVIRTUAL is called. This certainly works, but involves expanding stack frames, and is more expensive.

  2. Detect ACONST_NULL followed by INVOKEVIRTUAL. It probably works. But I'm not sure. Therefore, I'm asking the question here.


Solution

  • Assuming that obj.f is a non static, non interface, non superclass, non private method non inner/outer class method (edit: And also non varargs), then yes, I think it is safe to assume in practice. Of course, javac could always be changed tomorrow, but it is hard to immagine changing this, since it is the simplest and most natural way to compile the corresponding code.

    Note that if any of the conditions listed above are true, it will probably be compiled differently. For example a static method will obviously use invokestatic instead of invokevirtual. If the method is being invoked on an outer class from an inner class, it will probably call a compiler generated synthetic method instead, and so on.