Java bytecode "excessive" number of duplicates considered "poor" code?

This is a two-part question, but it does not make sense to separate parts. Is there a large number of dup instructions in bytecode to display an indicator of poorly written code? Where large is determined by a percentage of all bytecode instructions. Next, how to rewrite the code that generates the dup statement?

+8
java performance optimization bytecode
source share
3 answers

Are we talking about javac output you are analyzing, or about your own compiler / generator? If you are concerned about the quality of your Java code in terms of what javac produces, forget about it. First of all, javac creates suboptimal bytecode and relies on the JVM / JIT to perform all optimizations (a very good choice). But still, the bytecode is probably much better than anything you can quickly find. This is similar to the question about the quality of the assembly code generated by the C compiler.

If you generate bytecode yourself, an excessive amount of dup may seem bad, but it may not affect performance. Remember that bytecode translates to assembly on the target machine. JVM is a stack machine, but most architectures these days are registry-based. The fact that dup is only used because some bytecode instructions are destructive (the pop value from the operand stack when reading). This does not happen with registers - you can read them as many times as you want. Take the following code as an example:

 new java/lang/Object dup invokespecial java/lang/Object <init> ()V 

dup should be used here because invokespecial appears on top of the operand stack. Creating an object just to lose a reference to it after calling the constructor sounds like a bad idea. But in the assembly there is no dup , there is no copying and duplication of data. You will only have one CPU registry pointing to java/lang/Object .

In other words, the sub-optimal bytecode translates to a "more optimal" build on the fly. Just ... don't worry.

+7
source share

The dup instruction simply duplicates the top element of the operand stack. If the compiler knows that it will use the value several times over a relatively short period of time, it can choose to duplicate the value and hold it on the operand stack until it is needed.

One of the most common cases when you see dup is when you create an object and save it in a variable:

 Foo foo = new Foo(); 

Running javap -c will give you the following bytecode:

 0: new #1; //class Foo 3: dup 4: invokespecial #23; //Method "<init>":()V 7: astore_1 

In English: the new operation creates a new instance of the Foo object, and invokespecial executes the Foo constructor. Since you need a link in the stack to call the constructor, as well as to store in a variable, it makes sense to use dup (especially since the alternative, storing in a variable and then retrieving to start ctor may violate the Java memory model).

Here is the case where Oracle Java Compiler (1.6) did not use dup when I would expect this:

 int x = 12; public int bar(int z) { int y = x + x * 3; return y + z; } 

I expect the compiler to be a dup value of x , as it appears several times in the expression. Instead, enter the code that reloaded the value from the object:

 0: aload_0 1: getfield #12; //Field x:I 4: aload_0 5: getfield #12; //Field x:I 8: iconst_3 9: imul 10: iadd 

I would expect dup , because it is relatively expensive to get the value from the object (even after Hotspot does its magic), whereas two stack cells are likely to be on the same cache line.

+2
source share

If you are worried about the impact of dup and its relationship on performance, do not worry. The JVM does compilation on time, so it should not have any impact on performance.

Regarding code quality, there are two main reasons that will cause Javac to generate dup statements. The first is the creation of an object where it is inevitable. The second is the specific use of immediate meanings in expressions. If you will see much later, this may be a bad quality code, because usually you do not want such complex expressions in your source code (this was less readable).

Other dup versions ( dup_x1 , dup_x2 , dup2 , dup2_x1 and dup2_x2 ) are especially problematic because the instance object does not use them, so this almost certainly means that later. Of course, even then this is not a huge problem. All this means that the source code is not as readable as it can be.

If the code is not compiled with Java, all bets are disabled. The presence or absence of instructions does not really tell you much, especially in languages ​​whose compilers optimize compile time.

+1
source share

All Articles