1 /*
   2  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * @test
  28  * @bug 8022186
  29  * @summary javac generates dead code if a try with an empty body has a finalizer
  30  * @modules jdk.compiler/com.sun.tools.classfile
  31  *          jdk.compiler/com.sun.tools.javac.util
  32  */
  33 
  34 import com.sun.tools.classfile.Attribute;
  35 import com.sun.tools.classfile.ClassFile;
  36 import com.sun.tools.classfile.Code_attribute;
  37 import com.sun.tools.classfile.ConstantPool;
  38 import com.sun.tools.classfile.ConstantPool.CONSTANT_String_info;
  39 import com.sun.tools.classfile.ConstantPool.CPInfo;
  40 import com.sun.tools.classfile.ConstantPool.InvalidIndex;
  41 import com.sun.tools.classfile.Instruction;
  42 import com.sun.tools.classfile.Instruction.KindVisitor;
  43 import com.sun.tools.classfile.Instruction.TypeKind;
  44 import com.sun.tools.classfile.Method;
  45 import com.sun.tools.javac.util.Assert;
  46 import java.io.BufferedInputStream;
  47 import java.nio.file.Files;
  48 import java.nio.file.Path;
  49 import java.nio.file.Paths;
  50 
  51 public class DeadCodeGeneratedForEmptyTryTest {
  52 
  53     public static void main(String[] args) throws Exception {
  54         new DeadCodeGeneratedForEmptyTryTest().run();
  55     }
  56 
  57     void run() throws Exception {
  58         checkClassFile(Paths.get(System.getProperty("test.classes"),
  59                 this.getClass().getName() + "$Test.class"));
  60     }
  61 
  62     int utf8Index;
  63     int numberOfRefToStr = 0;
  64     ConstantPool constantPool;
  65 
  66     void checkClassFile(final Path path) throws Exception {
  67         ClassFile classFile = ClassFile.read(
  68                 new BufferedInputStream(Files.newInputStream(path)));
  69         constantPool = classFile.constant_pool;
  70         utf8Index = constantPool.getUTF8Index("STR_TO_LOOK_FOR");
  71         for (Method method: classFile.methods) {
  72             if (method.getName(constantPool).equals("methodToLookFor")) {
  73                 Code_attribute codeAtt = (Code_attribute)method.attributes.get(Attribute.Code);
  74                 for (Instruction inst: codeAtt.getInstructions()) {
  75                     inst.accept(codeVisitor, null);
  76                 }
  77             }
  78         }
  79         Assert.check(numberOfRefToStr == 1,
  80                 "There should only be one reference to a CONSTANT_String_info structure in the generated code");
  81     }
  82 
  83     CodeVisitor codeVisitor = new CodeVisitor();
  84 
  85     class CodeVisitor implements KindVisitor<Void, Void> {
  86 
  87         void checkIndirectRefToString(int cp_index) {
  88             try {
  89                 CPInfo cInfo = constantPool.get(cp_index);
  90                 if (cInfo instanceof CONSTANT_String_info) {
  91                     CONSTANT_String_info strInfo = (CONSTANT_String_info)cInfo;
  92                     if (strInfo.string_index == utf8Index) {
  93                         numberOfRefToStr++;
  94                     }
  95                 }
  96             } catch (InvalidIndex ex) {
  97                 throw new AssertionError("invalid constant pool index at " + cp_index);
  98             }
  99         }
 100 
 101         @Override
 102         public Void visitNoOperands(Instruction instr, Void p) {
 103             return null;
 104         }
 105 
 106         @Override
 107         public Void visitArrayType(Instruction instr, TypeKind kind, Void p) {
 108             return null;
 109         }
 110 
 111         @Override
 112         public Void visitBranch(Instruction instr, int offset, Void p) {
 113             return null;
 114         }
 115 
 116         @Override
 117         public Void visitConstantPoolRef(Instruction instr, int index, Void p) {
 118             checkIndirectRefToString(index);
 119             return null;
 120         }
 121 
 122         @Override
 123         public Void visitConstantPoolRefAndValue(Instruction instr, int index, int value, Void p) {
 124             checkIndirectRefToString(index);
 125             return null;
 126         }
 127 
 128         @Override
 129         public Void visitLocal(Instruction instr, int index, Void p) {
 130             return null;
 131         }
 132 
 133         @Override
 134         public Void visitLocalAndValue(Instruction instr, int index, int value, Void p) {
 135             return null;
 136         }
 137 
 138         @Override
 139         public Void visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, Void p) {
 140             return null;
 141         }
 142 
 143         @Override
 144         public Void visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, Void p) {
 145             return null;
 146         }
 147 
 148         @Override
 149         public Void visitValue(Instruction instr, int value, Void p) {
 150             return null;
 151         }
 152 
 153         @Override
 154         public Void visitUnknown(Instruction instr, Void p) {
 155             return null;
 156         }
 157 
 158     }
 159 
 160     public class Test {
 161         void methodToLookFor() {
 162             try {
 163             } finally {
 164                 System.out.println("STR_TO_LOOK_FOR");
 165             }
 166         }
 167     }
 168 }