Remove unused fields Remove unnecessary parts of compiled files Reduce necessary parts of compiled files Alter access control to speed up invocations

- 64 - x = x + 5; y = x2; z = x 4; These lines can be replaced by faster operations without altering the meaning of any statements: x += 5; Assignment in place is faster y = x 1; each right shift by one place is equivalent to dividing by 2 z = x 2; each left shift by one place is equivalent to multiplying by 2 These examples are the most common cases of strength reduction. All the shorthand arithmetic operators ++ , -- , += , -= , = , = , |= , = are computationally faster than their nonshorthand expansions, and should be used by the coder or replaced by the compiler where appropriate. [5] [5] One of the technical reviewers for this book, Ethan Henry, has pointed out to me that there is no actual guarantee that these strength reductions are more efficient in Java. This is true. However, they seem to work for at least some VMs. In addition, compilers producing native code including JIT compilers should produce faster code, as these techniques do work at the machine-code level.

3.4.2.5 Replace runtime computations with compiled results

An optimizing compiler can identify code that requires runtime execution if bytecodes are directly generated, but can be replaced by computing the result of that code during the compilation phase. The result can then replace the code. This technique is applied by most compilers for the simple case of literal folding see Section 3.5.1.1 and Section 3.5.1.2 . And it can be extended to other structures by adding some semantic input to the compiler. A simple example is: String S_NINETY = 90; int I_NINETY = Integer.parseIntS_NINETY; Although it is unlikely that anyone would do exactly this, similar kinds of initializations are used. An optimizing compiler that understood what Integer.parseInt did could calculate the resulting int value and insert that result directly into the compiled file, thus avoiding the runtime calculation.

3.4.2.6 Remove unused fields

Analysis of the application can identify fields of objects that are never used, and these fields can then be removed. This makes the runtime take less memory and improves the speeds of both the object creation and the garbage collection of these objects. The type of analysis described in the earlier section Section 3.4.2.1 improves the identification of unused fields.

3.4.2.7 Remove unnecessary parts of compiled files

Removing some unnecessary parts of compiled files is standard with most optimizing compilers. This option removes line number tables and local variable tables. The Java .class file structure allows extra information to be inserted, and some optimizing compilers make an effort to remove everything that is not necessary for runtime execution. This can be useful when it is important to minimize the size of the class files. Note that frequently, compilers with this capability can remove unnecessary parts of files that are already compiled, e.g., from third-party .class files you do not have the source for.

3.4.2.8 Reduce necessary parts of compiled files

- 65 - Some optimizing compilers can reduce the necessary parts of compiled files. For example, the .class file includes a pool of constants a structure containing various constants, and an optimizing compiler can minimize the size of the constant pool by combining and reducing entries.

3.4.2.9 Alter access control to speed up invocations

At least one optimizing compiler the DashO optimizer by PreEmptive provides the option to alter the access control to methods. The rationale for this is that any non- public method has access control on that method since it is access restricted, i.e., the runtime system must verify at some point that the caller to a method has access to calling that method. However, public methods require no such runtime checks. So the thinking is that any non- public method must have some overhead compared to an identical method declared as public . The result is that the compiler supports normal compilation so that any incorrect accesses are caught at the compilation stage, and the subsequent compiled class can have all its methods changed to public . This is, of course, a security risk.

3.4.2.10 Inline calls