1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.optimize.info; 22 23 import proguard.classfile.*; 24 import proguard.classfile.constant.*; 25 import proguard.classfile.constant.visitor.ConstantVisitor; 26 import proguard.classfile.util.SimplifiedVisitor; 27 import proguard.classfile.visitor.*; 28 29 /** 30 * This ClassVisitor marks all class members that can not be made private in the 31 * classes that it visits, and in the classes to which they refer. 32 * 33 * @author Eric Lafortune 34 */ 35 public class NonPrivateMemberMarker 36 extends SimplifiedVisitor 37 implements ClassVisitor, 38 ConstantVisitor, 39 MemberVisitor 40 { 41 private final MethodImplementationFilter filteredMethodMarker = new MethodImplementationFilter(this); 42 43 44 // Implementations for ClassVisitor. 45 visitProgramClass(ProgramClass programClass)46 public void visitProgramClass(ProgramClass programClass) 47 { 48 // Mark all referenced class members in different classes. 49 programClass.constantPoolEntriesAccept(this); 50 51 // Explicitly mark the <clinit> method. 52 programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT, 53 ClassConstants.METHOD_TYPE_CLINIT, 54 this); 55 56 // Explicitly mark the parameterless <init> method. 57 programClass.methodAccept(ClassConstants.METHOD_NAME_INIT, 58 ClassConstants.METHOD_TYPE_INIT, 59 this); 60 61 // Mark all methods that may have implementations. 62 programClass.methodsAccept(filteredMethodMarker); 63 } 64 65 visitLibraryClass(LibraryClass libraryClass)66 public void visitLibraryClass(LibraryClass libraryClass) 67 { 68 // Go over all methods. 69 libraryClass.methodsAccept(this); 70 } 71 72 73 // Implementations for ConstantVisitor. 74 visitAnyConstant(Clazz clazz, Constant constant)75 public void visitAnyConstant(Clazz clazz, Constant constant) {} 76 77 visitStringConstant(Clazz clazz, StringConstant stringConstant)78 public void visitStringConstant(Clazz clazz, StringConstant stringConstant) 79 { 80 // The referenced class member, if any, can never be made private, 81 // even if it's in the same class. 82 stringConstant.referencedMemberAccept(this); 83 } 84 85 visitAnyRefConstant(Clazz clazz, RefConstant refConstant)86 public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) 87 { 88 Clazz referencedClass = refConstant.referencedClass; 89 90 // Is it referring to a class member in another class? 91 // The class member might be in another class, or 92 // it may be referenced through another class. 93 if (referencedClass != null && 94 !referencedClass.equals(clazz) || 95 !refConstant.getClassName(clazz).equals(clazz.getName())) 96 { 97 // The referenced class member can never be made private. 98 refConstant.referencedMemberAccept(this); 99 } 100 } 101 102 103 // Implementations for MemberVisitor. 104 visitProgramField(ProgramClass programClass, ProgramField programField)105 public void visitProgramField(ProgramClass programClass, ProgramField programField) 106 { 107 markCanNotBeMadePrivate(programField); 108 } 109 110 visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)111 public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) 112 { 113 markCanNotBeMadePrivate(libraryField); 114 } 115 116 visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)117 public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 118 { 119 markCanNotBeMadePrivate(programMethod); 120 } 121 122 visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)123 public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod) 124 { 125 markCanNotBeMadePrivate(libraryMethod); 126 } 127 128 129 // Small utility methods. 130 markCanNotBeMadePrivate(Field field)131 private static void markCanNotBeMadePrivate(Field field) 132 { 133 FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field); 134 if (info != null) 135 { 136 info.setCanNotBeMadePrivate(); 137 } 138 } 139 140 141 /** 142 * Returns whether the given field can be made private. 143 */ canBeMadePrivate(Field field)144 public static boolean canBeMadePrivate(Field field) 145 { 146 FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field); 147 return info != null && 148 info.canBeMadePrivate(); 149 } 150 151 markCanNotBeMadePrivate(Method method)152 private static void markCanNotBeMadePrivate(Method method) 153 { 154 MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method); 155 if (info != null) 156 { 157 info.setCanNotBeMadePrivate(); 158 } 159 } 160 161 162 /** 163 * Returns whether the given method can be made private. 164 */ canBeMadePrivate(Method method)165 public static boolean canBeMadePrivate(Method method) 166 { 167 MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method); 168 return info != null && 169 info.canBeMadePrivate(); 170 } 171 } 172