view agent/src/share/classes/sun/jvm/hotspot/jdi/ArrayTypeImpl.java @ 17716:cdb71841f4bc

6498581: ThreadInterruptTest3 produces wrong output on Windows Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set. Reviewed-by: acorn, kvn Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author minqi
date Wed, 26 Feb 2014 15:20:41 -0800
parents c18cbe5936b8
children 29985fccf378
line wrap: on
line source

/*
 * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

package sun.jvm.hotspot.jdi;

import com.sun.jdi.*;

import sun.jvm.hotspot.oops.ArrayKlass;
import sun.jvm.hotspot.oops.InstanceKlass;
import sun.jvm.hotspot.oops.ObjArrayKlass;
import sun.jvm.hotspot.oops.TypeArrayKlass;
import sun.jvm.hotspot.oops.Klass;
import sun.jvm.hotspot.oops.Instance;
import sun.jvm.hotspot.oops.Symbol;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

public class ArrayTypeImpl extends ReferenceTypeImpl implements ArrayType {
  protected ArrayTypeImpl(VirtualMachine aVm, ArrayKlass aRef) {
        super(aVm, aRef);
    }

    public ArrayReference newInstance(int length) {
        vm.throwNotReadOnlyException("ArrayType.newInstance(int)");
        return null;
    }

    public String componentSignature() {
        return signature().substring(1); // Just skip the leading '['
    }

    public String componentTypeName() {
        JNITypeParser parser = new JNITypeParser(componentSignature());
        return parser.typeName();
    }

    public ClassLoaderReference classLoader() {
        if (ref() instanceof TypeArrayKlass) {
            // primitive array klasses are loaded by bootstrap loader
            return null;
        } else {
            Klass bottomKlass = ((ObjArrayKlass)ref()).getBottomKlass();
            if (bottomKlass instanceof TypeArrayKlass) {
                // multidimensional primitive array klasses are loaded by bootstrap loader
                return null;
            } else {
                // class loader of any other obj array klass is same as the loader
                // that loaded the bottom InstanceKlass
                Instance xx = (Instance)(((InstanceKlass) bottomKlass).getClassLoader());
                return vm.classLoaderMirror(xx);
            }
        }
    }

    void addVisibleMethods(Map methodMap) {
        // arrays don't have methods
    }

    List getAllMethods() {
        // arrays don't have methods
        // JLS says arrays have methods of java.lang.Object. But
        // JVMDI-JDI returns zero size list. We do the same here
        // for consistency.
        return new ArrayList(0);
    }

    /*
     * Find the type object, if any, of a component type of this array.
     * The component type does not have to be immediate; e.g. this method
     * can be used to find the component Foo of Foo[][].
     */
    public Type componentType() throws ClassNotLoadedException {
        ArrayKlass k = (ArrayKlass) ref();
        if (k instanceof ObjArrayKlass) {
            Klass elementKlass = ((ObjArrayKlass)k).getElementKlass();
            if (elementKlass == null) {
                throw new ClassNotLoadedException(componentSignature());
            } else {
                return vm.referenceType(elementKlass);
            }
        } else {
            // It's a primitive type
            return vm.primitiveTypeMirror(signature().charAt(1));
        }
    }

    static boolean isComponentAssignable(Type destination, Type source) {
        if (source instanceof PrimitiveType) {
            // Assignment of primitive arrays requires identical
            // component types.
            return source.equals(destination);
        } else {
           if (destination instanceof PrimitiveType) {
                return false;
            }

            ReferenceTypeImpl refSource = (ReferenceTypeImpl)source;
            ReferenceTypeImpl refDestination = (ReferenceTypeImpl)destination;
            // Assignment of object arrays requires availability
            // of widening conversion of component types
            return refSource.isAssignableTo(refDestination);
        }
    }


    /*
    * Return true if an instance of the  given reference type
    * can be assigned to a variable of this type
    */
    boolean isAssignableTo(ReferenceType destType) {
        if (destType instanceof ArrayType) {
            try {
                Type destComponentType = ((ArrayType)destType).componentType();
                return isComponentAssignable(destComponentType, componentType());
            } catch (ClassNotLoadedException e) {
                // One or both component types has not yet been
                // loaded => can't assign
                return false;
            }
        } else {
            Symbol typeName = ((ReferenceTypeImpl)destType).typeNameAsSymbol();
            if (destType instanceof InterfaceType) {
                // Every array type implements java.io.Serializable and
                // java.lang.Cloneable. fixme in JVMDI-JDI, includes only
                // Cloneable but not Serializable.
                return typeName.equals(vm.javaLangCloneable()) ||
                       typeName.equals(vm.javaIoSerializable());
            } else {
                // Only valid ClassType assignee is Object
                return typeName.equals(vm.javaLangObject());
            }
        }
    }

    List inheritedTypes() {
        // arrays are derived from java.lang.Object and
        // B[] is derived from A[] if B is derived from A.
        // But JVMDI-JDI returns zero sized list and we do the
        // same for consistency.
        return new ArrayList(0);
    }

    int getModifiers() {
        /*
         * For object arrays, the return values for Interface
         * Accessible.isPrivate(), Accessible.isProtected(),
         * etc... are the same as would be returned for the
         * component type.  Fetch the modifier bits from the
         * component type and use those.
         *
         * For primitive arrays, the modifiers are always
         *   VMModifiers.FINAL | VMModifiers.PUBLIC
         *
         * Reference com.sun.jdi.Accessible.java.
         */
        try {
            Type t = componentType();
            if (t instanceof PrimitiveType) {
                return VMModifiers.FINAL | VMModifiers.PUBLIC;
            } else {
                ReferenceType rt = (ReferenceType)t;
                return rt.modifiers();
            }
        } catch (ClassNotLoadedException cnle) {
            cnle.printStackTrace();
        }
        return -1;
    }

    public String toString() {
       return "array class " + name() + " (" + loaderString() + ")";
    }

    /*
     * Save a pointless trip over the wire for these methods
     * which have undefined results for arrays.
     */
    public boolean isPrepared() { return true; }
    public boolean isVerified() { return true; }
    public boolean isInitialized() { return true; }
    public boolean failedToInitialize() { return false; }
    public boolean isAbstract() { return false; }

    /*
     * Defined always to be true for arrays
     */
    public boolean isFinal() { return true; }
}