Is “final” final at runtime?

独自空忆成欢 提交于 2019-12-03 23:44:10

Is “final” final at runtime?

Not in the sense you mean.

AFAIK, the semantics of the final modifier are only enforced by the bytecode compiler.

There are no special bytecodes for initializing final fields, and the bytecode verifier (apparently) doesn't check for "illegal" assignments either.

However, the JIT compiler might treat the final modifier as a hint that things don't need to be refetched. So, if your bytecodes modify a variable marked as final you are liable to cause unpredictable behavior. (And the same thing can happen if you use reflection to modify a final variable. The spec clearly says so ...)

And, of course, you can modify a final field using reflection.


UPDATE

I took a look at the Java 7 JVM spec, and it partly contradicts what I said above. Specifically, the description of the PutField opcode says:

"Linking Exceptions ... Otherwise, if the field is final, it must be declared in the current class, and the instruction must occur in an instance initialization method (<init>) of the current class. Otherwise, an IllegalAccessError is thrown.".

So, while you could (in theory) assign to a final field multiple times in the object's constructor, the bytecode verifier should prevent any attempt to load a method that contains bytecode that assign to a final. Which ... when you think about Java security sandboxes ... is a good thing.

If the field is final it still may have situation when it is assigned to. For example in constructor. This logic is enforced by compiler as stated in this article. JVM itself would not enforce such rules as performance price would be too high and byte code verifier may not be able to easily determine if field is assigned only once.

So making the field final via ASM, probably does not make much sense.

You can overwrite final fields at runtime using reflection. Gson does this all time time while binding JSON to Java objects.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!