• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2009 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.INTERNAL_METHOD_NAME_CLINIT,
53                                   ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
54                                   this);
55 
56         // Explicitly mark the parameterless <init> method.
57         programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT,
58                                   ClassConstants.INTERNAL_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         Clazz referencedClass = stringConstant.referencedClass;
81 
82         // Is it refering to another class or class member?
83         if (referencedClass != null &&
84             !referencedClass.equals(clazz))
85         {
86             // The referenced class member, if any, can never be made private.
87             stringConstant.referencedMemberAccept(this);
88         }
89     }
90 
91 
visitAnyRefConstant(Clazz clazz, RefConstant refConstant)92     public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
93     {
94         Clazz referencedClass = refConstant.referencedClass;
95 
96         // Is it refering to a class member in another class?
97         // The class member might be in another class, or
98         // it may be referenced through another class.
99         if (referencedClass != null &&
100             !referencedClass.equals(clazz) ||
101             !refConstant.getClassName(clazz).equals(clazz.getName()))
102         {
103             // The referenced class member can never be made private.
104             refConstant.referencedMemberAccept(this);
105         }
106     }
107 
108 
109     // Implementations for MemberVisitor.
110 
visitProgramField(ProgramClass programClass, ProgramField programField)111     public void visitProgramField(ProgramClass programClass, ProgramField programField)
112     {
113         markCanNotBeMadePrivate(programField);
114     }
115 
116 
visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)117     public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
118     {
119         markCanNotBeMadePrivate(libraryField);
120     }
121 
122 
visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)123     public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
124     {
125         markCanNotBeMadePrivate(programMethod);
126     }
127 
128 
visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)129     public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
130     {
131         markCanNotBeMadePrivate(libraryMethod);
132     }
133 
134 
135     // Small utility methods.
136 
markCanNotBeMadePrivate(Field field)137     private static void markCanNotBeMadePrivate(Field field)
138     {
139         FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
140         if (info != null)
141         {
142             info.setCanNotBeMadePrivate();
143         }
144     }
145 
146 
147     /**
148      * Returns whether the given field can be made private.
149      */
canBeMadePrivate(Field field)150     public static boolean canBeMadePrivate(Field field)
151     {
152         FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
153         return info != null &&
154                info.canBeMadePrivate();
155     }
156 
157 
markCanNotBeMadePrivate(Method method)158     private static void markCanNotBeMadePrivate(Method method)
159     {
160         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
161         if (info != null)
162         {
163             info.setCanNotBeMadePrivate();
164         }
165     }
166 
167 
168     /**
169      * Returns whether the given method can be made private.
170      */
canBeMadePrivate(Method method)171     public static boolean canBeMadePrivate(Method method)
172     {
173         MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
174         return info != null &&
175                info.canBeMadePrivate();
176     }
177 }
178