Source code analysis: calls to wrapper class constructors

Dan Smith daniel.smith at oracle.com
Wed Oct 28 15:49:49 UTC 2020


> On Oct 27, 2020, at 10:56 PM, John Rose <john.r.rose at oracle.com> wrote:
> 
> One of the reasons it’s not going to be comprehensive
> is code like new Integer(complicatedExpr()), in which
> the `new` and `invokespecial <init>` are separated
> by (almost) arbitrarily complex bytecode.


> On Oct 28, 2020, at 3:25 AM, Remi Forax <forax at univ-mlv.fr> wrote:
> 
> I believe there is a quick and dirty trick,
> replace new java/lang/Integer by 3 NOPs and replace INVOKESPECIAL java/lang/Integer <init> (I)V by INVOKESTATIC java/lang/Integer valueOf (I)Ljava/lang/Integer;
> 
> It has to be done after the code is verified because the new execution doesn't push java/lang/Integer on the stack anymore before calling the arbitrary init expression thus any StackMapTables in between the NOPs and INVOKESTATIC are invalid.

Don't forget the 'dup'. We're assuming a 'new' immediately followed by 'dup' (4 nops), and code that will eventually consume the second one and leave the first one fully-initialized.

You're right that this disrupts verification; I think we can address this pre-verification by rewriting the StackMapTable, eliminating all references to 'uninitialized(Offset)' and shrinking the stack by two.

The bigger limitation, which I don't think you run into in any javac-generated code, is that you can put a copy of the uninitialized object reference anywhere you want—in locals, duplicated 15 times on the stack, etc. That's the point where I'm guessing we give up.

So, there's a tractable rewrite for any code with the shape:

new java/lang/Integer;
dup;
... [ad hoc computation, as long as it doesn't touch the two uninitialized Integer refs]
invokespecial java/lang/Integer.<init>(...)V;



More information about the valhalla-spec-observers mailing list