📄 referencevalue.java
字号:
/* * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package proguard.evaluation.value;import proguard.classfile.*;import proguard.classfile.visitor.ClassCollector;import proguard.classfile.util.ClassUtil;import java.util.*;/** * This class represents a partially evaluated reference value. It has a type * and a flag that indicates whether the value could be <code>null</code>. If * the type is <code>null</code>, the value is <code>null</code>. * * @author Eric Lafortune */public class ReferenceValue extends Category1Value{ private static final boolean DEBUG = false; private String type; private Clazz referencedClass; private boolean mayBeNull; /** * Creates a new ReferenceValue. */ public ReferenceValue(String type, Clazz referencedClass, boolean mayBeNull) { this.type = type; this.referencedClass = referencedClass; this.mayBeNull = mayBeNull; } /** * Returns the type. */ public String getType() { return type; } /** * Returns the class that is referenced by the type. */ public Clazz getReferencedClass() { return referencedClass; } // Basic unary methods. /** * Returns whether the type is <code>null</code>. */ public int isNull() { return type == null ? ALWAYS : mayBeNull ? MAYBE : NEVER; } /** * Returns whether the type is an instance of the given type. */ public int instanceOf(String otherType, Clazz otherReferencedClass) { String thisType = this.type; // If this type is null, it is never an instance of any class. if (thisType == null) { return NEVER; } // Start taking into account the type dimensions. int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); // Strip any common array prefixes. thisType = thisType.substring(commonDimensionCount); otherType = otherType.substring(commonDimensionCount); // If either stripped type is a primitive type, we can tell right away. if (commonDimensionCount > 0 && (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) || ClassUtil.isInternalPrimitiveType(otherType.charAt(0)))) { return !thisType.equals(otherType) ? NEVER : mayBeNull ? MAYBE : ALWAYS; } // Strip the class type prefix and suffix of this type, if any. if (thisDimensionCount == commonDimensionCount) { thisType = ClassUtil.internalClassNameFromClassType(thisType); } // Strip the class type prefix and suffix of the other type, if any. if (otherDimensionCount == commonDimensionCount) { otherType = ClassUtil.internalClassNameFromClassType(otherType); } // If this type is an array type, and the other type is not // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, // this type can never be an instance. if (thisDimensionCount > otherDimensionCount && !ClassUtil.isInternalArrayInterfaceName(otherType)) { return NEVER; } // If the other type is an array type, and this type is not // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, // this type can never be an instance. if (thisDimensionCount < otherDimensionCount && !ClassUtil.isInternalArrayInterfaceName(thisType)) { return NEVER; } // If this type may be null, it might not be an instance of any class. if (mayBeNull) { return MAYBE; } // If this type is equal to the other type, or if the other type is // java.lang.Object, this type is always an instance. if (thisType.equals(otherType) || ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT.equals(otherType)) { return ALWAYS; } // If this type is an array type, it's ok. if (thisDimensionCount > otherDimensionCount) { return ALWAYS; } // If the other type is an array type, it might be ok. if (thisDimensionCount < otherDimensionCount) { return MAYBE; } // If the value extends the type, we're sure. return referencedClass != null && otherReferencedClass != null && referencedClass.extendsOrImplements(otherReferencedClass) ? ALWAYS : MAYBE; } /** * Returns the length of the array, assuming this type is an array. */ public IntegerValue arrayLength(ValueFactory valueFactory) { return valueFactory.createIntegerValue(); } /** * Returns the value of the array at the given index, assuming this type * is an array. */ public Value arrayLoad(IntegerValue integerValue, ValueFactory valueFactory) { return type == null ? ValueFactory.REFERENCE_VALUE_NULL : !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : valueFactory.createValue(type.substring(1), referencedClass, true); } // Basic binary methods. /** * Returns the generalization of this ReferenceValue and the given other * ReferenceValue. */ public ReferenceValue generalize(ReferenceValue other) { String thisType = this.type; String otherType = other.type; // If both types are nul, the generalization is null too. if (thisType == null && otherType == null) { return ValueFactory.REFERENCE_VALUE_NULL; } // If this type is null, the generalization is the other type, maybe null. if (thisType == null) { return other.generalizeMayBeNull(true); } // If the other type is null, the generalization is this type, maybe null. if (otherType == null) { return this.generalizeMayBeNull(true); } boolean mayBeNull = this.mayBeNull || other.mayBeNull; // If the two types are equal, the generalization remains the same, maybe null. if (thisType.equals(otherType)) { return this.generalizeMayBeNull(mayBeNull); } // Start taking into account the type dimensions. int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); if (thisDimensionCount == otherDimensionCount) { // See if we can take into account the referenced classes. Clazz thisReferencedClass = this.referencedClass; Clazz otherReferencedClass = other.referencedClass;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -