1 /* 2 * Copyright (c) 1998, 2017, 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 package com.sun.tools.jdi; 27 28 import java.util.ArrayList; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Set; 33 34 import com.sun.jdi.ArrayReference; 35 import com.sun.jdi.ArrayType; 36 import com.sun.jdi.ClassLoaderReference; 37 import com.sun.jdi.ClassNotLoadedException; 38 import com.sun.jdi.InterfaceType; 39 import com.sun.jdi.Method; 40 import com.sun.jdi.PrimitiveType; 41 import com.sun.jdi.ReferenceType; 42 import com.sun.jdi.Type; 43 import com.sun.jdi.VirtualMachine; 44 45 public class ArrayTypeImpl extends ReferenceTypeImpl 46 implements ArrayType 47 { 48 protected ArrayTypeImpl(VirtualMachine aVm, long aRef) { 49 super(aVm, aRef); 50 } 51 52 public ArrayReference newInstance(int length) { 53 try { 54 return (ArrayReference)JDWP.ArrayType.NewInstance. 55 process(vm, this, length).newArray; 56 } catch (JDWPException exc) { 57 throw exc.toJDIException(); 58 } 59 } 60 61 public String componentSignature() { 62 return signature().substring(1); // Just skip the leading '[' 63 } 64 65 public String componentTypeName() { 66 JNITypeParser parser = new JNITypeParser(componentSignature()); 67 return parser.typeName(); 68 } 69 70 Type type() throws ClassNotLoadedException { 71 return findType(componentSignature()); 72 } 73 74 @Override 75 void addVisibleMethods(Map<String, Method> map, Set<InterfaceType> seenInterfaces) { 76 // arrays don't have methods 77 } 78 79 public List<Method> allMethods() { 80 return new ArrayList<>(0); // arrays don't have methods 81 } 82 83 /* 84 * Find the type object, if any, of a component type of this array. 85 * The component type does not have to be immediate; e.g. this method 86 * can be used to find the component Foo of Foo[][]. This method takes 87 * advantage of the property that an array and its component must have 88 * the same class loader. Since array set operations don't have an 89 * implicit enclosing type like field and variable set operations, 90 * this method is sometimes needed for proper type checking. 91 */ 92 Type findComponentType(String signature) throws ClassNotLoadedException { 93 byte tag = (byte)signature.charAt(0); 94 if (PacketStream.isObjectTag(tag)) { 95 // It's a reference type 96 JNITypeParser parser = new JNITypeParser(componentSignature()); 97 List<ReferenceType> list = vm.classesByName(parser.typeName()); 98 Iterator<ReferenceType> iter = list.iterator(); 99 while (iter.hasNext()) { 100 ReferenceType type = iter.next(); 101 ClassLoaderReference cl = type.classLoader(); 102 if ((cl == null)? 103 (classLoader() == null) : 104 (cl.equals(classLoader()))) { 105 return type; 106 } 107 } 108 // Component class has not yet been loaded 109 throw new ClassNotLoadedException(componentTypeName()); 110 } else { 111 // It's a primitive type 112 return vm.primitiveTypeMirror(tag); 113 } 114 } 115 116 public Type componentType() throws ClassNotLoadedException { 117 return findComponentType(componentSignature()); 118 } 119 120 static boolean isComponentAssignable(Type destination, Type source) { 121 if (source instanceof PrimitiveType) { 122 // Assignment of primitive arrays requires identical 123 // component types. 124 return source.equals(destination); 125 } else { 126 if (destination instanceof PrimitiveType) { 127 return false; 128 } 129 130 ReferenceTypeImpl refSource = (ReferenceTypeImpl)source; 131 ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination; 132 // Assignment of object arrays requires availability 133 // of widening conversion of component types 134 return refSource.isAssignableTo(refDestination); 135 } 136 } 137 138 /* 139 * Return true if an instance of the given reference type 140 * can be assigned to a variable of this type 141 */ 142 boolean isAssignableTo(ReferenceType destType) { 143 if (destType instanceof ArrayType) { 144 try { 145 Type destComponentType = ((ArrayType)destType).componentType(); 146 return isComponentAssignable(destComponentType, componentType()); 147 } catch (ClassNotLoadedException e) { 148 // One or both component types has not yet been 149 // loaded => can't assign 150 return false; 151 } 152 } else if (destType instanceof InterfaceType) { 153 // Only valid InterfaceType assignee is Cloneable 154 return destType.name().equals("java.lang.Cloneable"); 155 } else { 156 // Only valid ClassType assignee is Object 157 return destType.name().equals("java.lang.Object"); 158 } 159 } 160 161 List<ReferenceType> inheritedTypes() { 162 return new ArrayList<ReferenceType>(0); 163 } 164 165 void getModifiers() { 166 if (modifiers != -1) { 167 return; 168 } 169 /* 170 * For object arrays, the return values for Interface 171 * Accessible.isPrivate(), Accessible.isProtected(), 172 * etc... are the same as would be returned for the 173 * component type. Fetch the modifier bits from the 174 * component type and use those. 175 * 176 * For primitive arrays, the modifiers are always 177 * VMModifiers.FINAL | VMModifiers.PUBLIC 178 * 179 * Reference com.sun.jdi.Accessible.java. 180 */ 181 try { 182 Type t = componentType(); 183 if (t instanceof PrimitiveType) { 184 modifiers = VMModifiers.FINAL | VMModifiers.PUBLIC; 185 } else { 186 ReferenceType rt = (ReferenceType)t; 187 modifiers = rt.modifiers(); 188 } 189 } catch (ClassNotLoadedException cnle) { 190 cnle.printStackTrace(); 191 } 192 } 193 194 public String toString() { 195 return "array class " + name() + " (" + loaderString() + ")"; 196 } 197 198 /* 199 * Save a pointless trip over the wire for these methods 200 * which have undefined results for arrays. 201 */ 202 public boolean isPrepared() { return true; } 203 public boolean isVerified() { return true; } 204 public boolean isInitialized() { return true; } 205 public boolean failedToInitialize() { return false; } 206 public boolean isAbstract() { return false; } 207 208 /* 209 * Defined always to be true for arrays 210 */ 211 public boolean isFinal() { return true; } 212 213 /* 214 * Defined always to be false for arrays 215 */ 216 public boolean isStatic() { return false; } 217 }