alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (BasicTypeDataBase.java)

This example Java source code file (BasicTypeDataBase.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

address, basictypedatabase, debug, hashmap, integer, internalerror, iterator, long, machinedescription, runtimeexception, type, util, vtblaccess

The BasicTypeDataBase.java Java example source code

/*
 * Copyright (c) 2000, 2013, 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.types.basic;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import sun.jvm.hotspot.debugger.Address;
import sun.jvm.hotspot.debugger.MachineDescription;
import sun.jvm.hotspot.runtime.VM;
import sun.jvm.hotspot.types.Type;
import sun.jvm.hotspot.types.TypeDataBase;

/** <P> This is a basic implementation of the TypeDataBase interface.
    It allows an external type database builder to add types to be
    consumed by a client through the Type interfaces. It has no
    knowledge of symbol lookup; for example, the builder is
    responsible for providing the addresses of static fields. </P>

    <P> Among other things, the database builder is responsible for
    providing the Types for the Java primitive types, as well as their
    sizes. </P>
*/

public class BasicTypeDataBase implements TypeDataBase {
  private MachineDescription machDesc;
  private VtblAccess vtblAccess;
  /** Maps strings to Type objects. This does not contain the primitive types. */
  private Map nameToTypeMap = new HashMap();
  /** Maps strings to Integers, used for enums, etc. */
  private Map nameToIntConstantMap = new HashMap();
  /** Maps strings to Longs, used for 32/64-bit constants, etc. */
  private Map nameToLongConstantMap = new HashMap();
  /** Primitive types. */
  private Type jbooleanType;
  private Type jbyteType;
  private Type jcharType;
  private Type jdoubleType;
  private Type jfloatType;
  private Type jintType;
  private Type jlongType;
  private Type jshortType;

  /** For debugging */
  private static final boolean DEBUG;
  static {
    DEBUG = System.getProperty("sun.jvm.hotspot.types.basic.BasicTypeDataBase.DEBUG") != null;
  }

  public BasicTypeDataBase(MachineDescription machDesc, VtblAccess vtblAccess) {
    this.machDesc   = machDesc;
    this.vtblAccess = vtblAccess;
  }

  public Type lookupType(String cTypeName) {
    return lookupType(cTypeName, true);
  }

  public Type lookupType(String cTypeName, boolean throwException) {
    Type type = (Type) nameToTypeMap.get(cTypeName);
    if (type == null && throwException) {
      throw new RuntimeException("No type named \"" + cTypeName + "\" in database");
    }
    return type;
  }

  public Integer lookupIntConstant(String constantName) {
    return lookupIntConstant(constantName, true);
  }

  public Integer lookupIntConstant(String constantName, boolean throwException) {
    Integer i = (Integer) nameToIntConstantMap.get(constantName);
    if (i == null) {
      if (throwException) {
        throw new RuntimeException("No integer constant named \"" + constantName + "\" present in type database");
      }
    }
    return i;
  }

  public Long lookupLongConstant(String constantName) {
    return lookupLongConstant(constantName, true);
  }

  public Long lookupLongConstant(String constantName, boolean throwException) {
    Long i = (Long) nameToLongConstantMap.get(constantName);
    if (i == null) {
      if (throwException) {
        throw new RuntimeException("No long constant named \"" + constantName + "\" present in type database");
      }
    }
    return i;
  }

  public Type getJBooleanType() {
    return jbooleanType;
  }

  public Type getJByteType() {
    return jbyteType;
  }

  public Type getJCharType() {
    return jcharType;
  }

  public Type getJDoubleType() {
    return jdoubleType;
  }

  public Type getJFloatType() {
    return jfloatType;
  }

  public Type getJIntType() {
    return jintType;
  }

  public Type getJLongType() {
    return jlongType;
  }

  public Type getJShortType() {
    return jshortType;
  }

  public long getAddressSize() {
    return machDesc.getAddressSize();
  }

  public long getOopSize() {
    return VM.getVM().getOopSize();
  }

  HashMap typeToVtbl = new HashMap();

  private Address vtblForType(Type type) {
    Address vtblAddr = (Address)typeToVtbl.get(type);
    if (vtblAddr == null) {
      vtblAddr = vtblAccess.getVtblForType(type);
      if (vtblAddr != null) {
        typeToVtbl.put(type, vtblAddr);
      }
    }
    return vtblAddr;
  }

  public boolean addressTypeIsEqualToType(Address addr, Type type) {
    if (addr == null) {
      return false;
    }

    // This implementation should be suitably platform-independent; we
    // search nearby memory for the vtbl value of the given type.

    Address vtblAddr = vtblForType(type);

    if (vtblAddr == null) {
      // Type was not polymorphic, or an error occurred during lookup
      if (DEBUG) {
        System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: vtblAddr == null");
      }

      return false;
    }

    // The first implementation searched three locations for this vtbl
    // value; scanning through the entire object was considered, but
    // we thought we knew where we were looking, and looking only in
    // these specific locations should reduce the probability of
    // mistaking random bits as a pointer (although, realistically
    // speaking, the likelihood of finding a match between the bit
    // pattern of, for example, a double and the vtbl is vanishingly
    // small.)
    //    1. The first word of the object (should handle MSVC++ as
    //    well as the SparcWorks compilers with compatibility set to
    //    v5.0 or greater)
    //    2. and 3. The last two Address-aligned words of the part of
    //    the object defined by its topmost polymorphic superclass.
    //    This should handle the SparcWorks compilers, v4.2 or
    //    earlier, as well as any other compilers which place the vptr
    //    at the end of the user-defined fields of the first base
    //    class with virtual functions.
    //
    // Unfortunately this algorithm did not work properly for the
    // specific case of the ThreadShadow/Thread inheritance situation,
    // because the Solaris compiler seems to cleverly eliminate the
    // vtbl for ThreadShadow since the only virtual is empty. (We
    // should get rid of the ThreadShadow and fix the include
    // databases, but need to postpone this for the present.) The
    // current solution performs the three-location check for this
    // class and all of its known superclasses rather than just the
    // topmost polymorphic one.

    Type curType = type;

    try {
      while (curType != null) {
        // Using the size information we have for this type, check the
        // three locations described above.

        // (1)
        if (vtblAddr.equals(addr.getAddressAt(0))) {
          return true;
        }

        // (2)
        long offset = curType.getSize();
        // I don't think this should be misaligned under any
        // circumstances, but I'm not sure (FIXME: also not sure which
        // way to go here, up or down -- assuming down)
        offset -= (offset % getAddressSize());
        if (offset <= 0) {
          return false;
        }
        if (vtblAddr.equals(addr.getAddressAt(offset))) {
          return true;
        }
        offset -= getAddressSize();
        if (offset <= 0) {
          return false;
        }
        if (vtblAddr.equals(addr.getAddressAt(offset))) {
          return true;
        }

        curType = curType.getSuperclass();
      }
    }
    catch (Exception e) {
      // Any UnmappedAddressExceptions, etc. are a good indication
      // that the pointer is not of the specified type
      if (DEBUG) {
        System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: exception occurred during lookup:");
        e.printStackTrace();
      }

      return false;
    }

    if (DEBUG) {
      System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: all vptr tests failed for type " +
                         type.getName());
    }

    return false;
  }

  public Type findDynamicTypeForAddress(Address addr, Type baseType) {
    // This implementation should be suitably platform-independent; we
    // search nearby memory for the vtbl value of the given type.

    if (vtblForType(baseType) == null) {
      // Type was not polymorphic which is an error of some sort
      throw new InternalError(baseType + " does not appear to be polymorphic");
    }

    // This is a more restricted version of guessTypeForAddress since
    // that function has some limitations since it doesn't really know
    // where in the hierarchy a virtual type starts and just poking
    // around in memory is likely to trip over some vtable address,
    // resulting in false positives.  Eventually all uses should
    // switch to this logic but in the interests of stability it will
    // be separate for the moment.

    // Assuming that the base type is truly the first polymorphic type
    // then the vtbl for all subclasss should be at several defined
    // locations so only those locations will be checked.  It's also
    // required that the caller knows that the static type is at least
    // baseType.  See the notes in guessTypeForAddress for the logic of
    // the locations searched.

    Address loc1 = addr.getAddressAt(0);
    Address loc2 = null;
    Address loc3 = null;
    long offset2 = baseType.getSize();
    // I don't think this should be misaligned under any
    // circumstances, but I'm not sure (FIXME: also not sure which
    // way to go here, up or down -- assuming down)
    offset2 = offset2 - (offset2 % getAddressSize()) - getAddressSize();
    if (offset2 > 0) {
      loc2 = addr.getAddressAt(offset2);
    }
    long offset3 = offset2 - getAddressSize();
    if (offset3 > 0) {
      loc3 = addr.getAddressAt(offset3);
    }

    Type loc2Match = null;
    Type loc3Match = null;
    for (Iterator iter = getTypes(); iter.hasNext(); ) {
      Type type = (Type) iter.next();
      Type superClass = type;
      while (superClass != baseType && superClass != null) {
        superClass = superClass.getSuperclass();
      }
      if (superClass == null) continue;
      Address vtblAddr = vtblForType(type);
      if (vtblAddr == null) {
        // This occurs sometimes for intermediate types that are never
        // instantiated.
        if (DEBUG) {
          System.err.println("null vtbl for " + type);
        }
        continue;
      }
      // Prefer loc1 match
      if (vtblAddr.equals(loc1)) return type;
      if (loc2 != null && loc2Match == null && vtblAddr.equals(loc2)) {
          loc2Match = type;
      }
      if (loc3 != null && loc3Match == null && vtblAddr.equals(loc3)) {
          loc3Match = type;
      }
    }
    if (loc2Match != null) return loc2Match;
    if (loc3Match != null) return loc3Match;
    return null;
  }

  public Type guessTypeForAddress(Address addr) {
    for (Iterator iter = getTypes(); iter.hasNext(); ) {
      Type t = (Type) iter.next();
      if (addressTypeIsEqualToType(addr, t)) {
        return t;
      }
    }
    return null;
  }

  public long cIntegerTypeMaxValue(long sizeInBytes, boolean isUnsigned) {
    return machDesc.cIntegerTypeMaxValue(sizeInBytes, isUnsigned);
  }

  public long cIntegerTypeMinValue(long sizeInBytes, boolean isUnsigned) {
    return machDesc.cIntegerTypeMinValue(sizeInBytes, isUnsigned);
  }

  public Iterator getTypes() {
    return nameToTypeMap.values().iterator();
  }

  public Iterator getIntConstants() {
    return nameToIntConstantMap.keySet().iterator();
  }

  public Iterator getLongConstants() {
    return nameToLongConstantMap.keySet().iterator();
  }

  //--------------------------------------------------------------------------------
  // Public routines only for use by the database builder
  //

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJBooleanType(Type type) {
    jbooleanType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJByteType(Type type) {
    jbyteType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJCharType(Type type) {
    jcharType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJDoubleType(Type type) {
    jdoubleType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJFloatType(Type type) {
    jfloatType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJIntType(Type type) {
    jintType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJLongType(Type type) {
    jlongType = type;
  }

  /** This method should only be called by the builder of the
      TypeDataBase and at most once */
  public void setJShortType(Type type) {
    jshortType = type;
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if a class with this
      name was already present. */
  public void addType(Type type) {
    if (nameToTypeMap.get(type.getName()) != null) {
      throw new RuntimeException("type of name \"" + type.getName() + "\" already present");
    }

    nameToTypeMap.put(type.getName(), type);
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if this class was not
      present. */
  public void removeType(Type type) {
    Type curType = (Type) nameToTypeMap.get(type.getName());
    if (curType == null) {
      throw new RuntimeException("type of name \"" + type.getName() + "\" not present");
    }

    if (!curType.equals(type)) {
      throw new RuntimeException("a different type of name \"" + type.getName() + "\" was present");
    }

    nameToTypeMap.remove(type.getName());
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if an integer constant
      with this name was already present. */
  public void addIntConstant(String name, int value) {
    if (nameToIntConstantMap.get(name) != null) {
      throw new RuntimeException("int constant of name \"" + name + "\" already present");
    }

    nameToIntConstantMap.put(name, new Integer(value));
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if an integer constant
      with this name was not present. */
  public void removeIntConstant(String name) {
    Integer curConstant = (Integer) nameToIntConstantMap.get(name);
    if (curConstant == null) {
      throw new RuntimeException("int constant of name \"" + name + "\" not present");
    }

    nameToIntConstantMap.remove(name);
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if a long constant with
      this name was already present. */
  public void addLongConstant(String name, long value) {
    if (nameToLongConstantMap.get(name) != null) {
      throw new RuntimeException("long constant of name \"" + name + "\" already present");
    }

    nameToLongConstantMap.put(name, new Long(value));
  }

  /** This method should only be used by the builder of the
      TypeDataBase. Throws a RuntimeException if a long constant with
      this name was not present. */
  public void removeLongConstant(String name) {
    Long curConstant = (Long) nameToLongConstantMap.get(name);
    if (curConstant == null) {
      throw new RuntimeException("long constant of name \"" + name + "\" not present");
    }

    nameToLongConstantMap.remove(name);
  }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java BasicTypeDataBase.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.