OSDN Git Service

Fix problem that caused compiled java code to trigger an internal gdb error.
[pf3gnuchains/gcc-fork.git] / libjava / defineclass.cc
index dc35002..111b1fb 100644 (file)
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -23,8 +23,10 @@ details.  */
 #include <java-interp.h>
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <java-cpool.h>
 #include <gcj/cni.h>
+#include <execution.h>
 
 #include <java/lang/Class.h>
 #include <java/lang/Float.h>
@@ -37,6 +39,7 @@ details.  */
 #include <java/lang/ClassCircularityError.h>
 #include <java/lang/IncompatibleClassChangeError.h>
 #include <java/lang/reflect/Modifier.h>
+#include <java/security/ProtectionDomain.h>
 
 using namespace gcj;
 
@@ -75,7 +78,7 @@ struct _Jv_ClassReader {
   // allways on.  You always want this as far as I can see, but it also
   // controls weither identifiers and type descriptors/signatures are
   // verified as legal.  This could be somewhat more expensive since it
-  // will call Characher.isJavaIdentifier{Start,Part} for each character
+  // will call Character.isJavaIdentifier{Start,Part} for each character
   // in any identifier (field name or method name) it comes by.  Thus,
   // it might be useful to turn off this verification for classes that
   // come from a trusted source.  However, for GCJ, trusted classes are
@@ -96,7 +99,10 @@ struct _Jv_ClassReader {
   unsigned int      *offsets;
 
   // the class to define (see java-interp.h)
-  _Jv_InterpClass   *def;
+  jclass          def;
+  
+  // the classes associated interpreter data.
+  _Jv_InterpClass  *def_interp;
 
   /* check that the given number of input bytes are available */
   inline void check (int num)
@@ -212,7 +218,8 @@ struct _Jv_ClassReader {
       throw_class_format_error ("erroneous type descriptor");
   }
 
-  _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length)
+  _Jv_ClassReader (jclass klass, jbyteArray data, jint offset, jint length,
+                  java::security::ProtectionDomain *pd)
   {
     if (klass == 0 || length < 0 || offset+length > data->length)
       throw_internal_error ("arguments to _Jv_DefineClass");
@@ -221,7 +228,12 @@ struct _Jv_ClassReader {
     bytes  = (unsigned char*) (elements (data)+offset);
     len    = length;
     pos    = 0;
-    def    = (_Jv_InterpClass*) klass;
+    def    = klass;
+
+    def->size_in_bytes = -1;
+    def->vtable_method_count = -1;
+    def->engine = &_Jv_soleInterpreterEngine;
+    def->protectionDomain = pd;
   }
 
   /** and here goes the parser members defined out-of-line */
@@ -268,9 +280,10 @@ struct _Jv_ClassReader {
 };
 
 void
-_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length)
+_Jv_DefineClass (jclass klass, jbyteArray data, jint offset, jint length,
+                java::security::ProtectionDomain *pd)
 {
-  _Jv_ClassReader reader (klass, data, offset, length);
+  _Jv_ClassReader reader (klass, data, offset, length, pd);
   reader.parse();
 
   /* that's it! */
@@ -306,8 +319,13 @@ _Jv_ClassReader::parse ()
 
   handleClassBegin (access_flags, this_class, super_class);
 
+  // Allocate our aux_info here, after the name is set, to fulfill our
+  // contract with the collector interface.
+  def->aux_info = (void *) _Jv_AllocBytes (sizeof (_Jv_InterpClass));
+  def_interp = (_Jv_InterpClass *) def->aux_info;
+
   int interfaces_count = read2u (); 
-       
+
   handleInterfacesBegin (interfaces_count);
 
   for (int i = 0; i < interfaces_count; i++)
@@ -330,10 +348,11 @@ _Jv_ClassReader::parse ()
   if (pos != len)
     throw_class_format_error ("unused data before end of file");
 
-  // tell everyone we're done.
-  def->state = JV_STATE_LOADED;
+  // Tell everyone we're done.
+  def->state = JV_STATE_READ;
+  if (gcj::verbose_class_flag)
+    _Jv_Linker::print_class_loaded (def);
   def->notifyAll ();
-
 }
 
 void _Jv_ClassReader::read_constpool ()
@@ -403,15 +422,15 @@ void _Jv_ClassReader::read_fields ()
       int name_index       = read2u ();
       int descriptor_index = read2u ();
       int attributes_count = read2u ();
-      
+
       check_tag (name_index, JV_CONSTANT_Utf8);
       prepare_pool_entry (name_index, JV_CONSTANT_Utf8);
 
       check_tag (descriptor_index, JV_CONSTANT_Utf8);
       prepare_pool_entry (descriptor_index, JV_CONSTANT_Utf8);
-      
+
       handleField (i, access_flags, name_index, descriptor_index);
-      
+
       for (int j = 0; j < attributes_count; j++)
        {
          read_one_field_attribute (i);
@@ -510,30 +529,20 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
        throw_class_format_error ("only one Exceptions attribute allowed per method");
 
       int num_exceptions = read2u ();
-      // We use malloc here because the GC won't scan the method
-      // objects.  FIXME this means a memory leak if we GC a class.
-      // (Currently we never do.)
       _Jv_Utf8Const **exceptions =
-       (_Jv_Utf8Const **) _Jv_Malloc ((num_exceptions + 1) * sizeof (_Jv_Utf8Const *));
+       (_Jv_Utf8Const **) _Jv_AllocBytes ((num_exceptions + 1)
+                                          * sizeof (_Jv_Utf8Const *));
 
       int out = 0;
       _Jv_word *pool_data = def->constants.data;
       for (int i = 0; i < num_exceptions; ++i)
        {
-         try
-           {
-             int ndx = read2u ();
-             // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
-             if (ndx != 0)
-               {
-                 check_tag (ndx, JV_CONSTANT_Class);
-                 exceptions[out++] = pool_data[ndx].utf8; 
-               }
-           }
-         catch (java::lang::Throwable *exc)
+         int ndx = read2u ();
+         // JLS 2nd Ed. 4.7.5 requires that the tag not be 0.
+         if (ndx != 0)
            {
-             _Jv_Free (exceptions);
-             throw exc;
+             check_tag (ndx, JV_CONSTANT_Class);
+             exceptions[out++] = pool_data[ndx].utf8; 
            }
        }
       exceptions[out] = NULL;
@@ -605,26 +614,54 @@ void _Jv_ClassReader::read_one_method_attribute (int method_index)
     }
 }
 
-void _Jv_ClassReader::read_one_code_attribute (int /*method*/
+void _Jv_ClassReader::read_one_code_attribute (int method_index
 {
-  /* ignore for now, ... later we may want to pick up
-     line number information, for debugging purposes;
-     in fact, the whole debugger issue is open!  */
-
-  /* int name = */ read2u ();
+  int name = read2u ();
   int length = read4 ();
-  skip (length);
-
+  if (is_attribute_name (name, "LineNumberTable"))
+    {
+      _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
+       (def_interp->interpreted_methods[method_index]);
+      if (method->line_table != NULL)
+       throw_class_format_error ("Method already has LineNumberTable");
+
+      int table_len = read2u ();
+      _Jv_LineTableEntry* table
+       = (_Jv_LineTableEntry *) JvAllocBytes (table_len
+                                           * sizeof (_Jv_LineTableEntry));
+      for (int i = 0; i < table_len; i++)
+       {
+        table[i].bytecode_pc = read2u ();
+        table[i].line = read2u ();
+       }
+      method->line_table_len = table_len;
+      method->line_table = table;
+    }
+  else
+    {
+      /* ignore unknown code attributes */
+      skip (length);
+    }
 }
 
 void _Jv_ClassReader::read_one_class_attribute () 
 {
-  /* we also ignore the class attributes, ...
-     some day we'll add inner-classes support. */
-
-  /* int name = */ read2u ();
+  int name = read2u ();
   int length = read4 ();
-  skip (length);
+  if (is_attribute_name (name, "SourceFile"))
+    {
+      int source_index = read2u ();
+      check_tag (source_index, JV_CONSTANT_Utf8);
+      prepare_pool_entry (source_index, JV_CONSTANT_Utf8);
+      def_interp->source_file_name = _Jv_NewStringUtf8Const
+       (def->constants.data[source_index].utf8);
+    }
+  else
+    {
+      /* Currently, we ignore most class attributes.
+         FIXME: Add inner-classes attributes support. */
+     skip (length);
+    }
 }
 
 
@@ -772,9 +809,9 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
                           name_index, type_index);
 
          if (this_tag == JV_CONSTANT_Fieldref)
-           _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
+           verify_field_signature (pool_data[type_index].utf8);
          else
-           _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
+           verify_method_signature (pool_data[type_index].utf8);
 
          _Jv_Utf8Const* name = pool_data[name_index].utf8;
 
@@ -847,8 +884,7 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
 
 
 void
-_Jv_ClassReader::handleClassBegin
-  (int access_flags, int this_class, int super_class)
+_Jv_ClassReader::handleClassBegin (int access_flags, int this_class, int super_class)
 {
   using namespace java::lang::reflect;
 
@@ -861,7 +897,7 @@ _Jv_ClassReader::handleClassBegin
   // was ClassLoader.defineClass called with an expected class name?
   if (def->name == 0)
     {
-      jclass orig = _Jv_FindClassInCache (loadedName, def->loader);
+      jclass orig = def->loader->findLoadedClass(loadedName->toString());
 
       if (orig == 0)
        {
@@ -884,13 +920,13 @@ _Jv_ClassReader::handleClassBegin
       jstring msg = JvNewStringUTF ("loaded class ");
       msg = msg->concat (def->getName ());
       msg = msg->concat (_Jv_NewStringUTF (" was in fact named "));
-      jstring klass_name = _Jv_NewStringUTF (loadedName->data);
+      jstring klass_name = loadedName->toString();
       msg = msg->concat (klass_name);
 
       throw_no_class_def_found_error (msg);
     }
 
-  def->accflags = access_flags;
+  def->accflags = access_flags | java::lang::reflect::Modifier::INTERPRETED;
   pool_data[this_class].clazz = def;
   pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
 
@@ -901,16 +937,14 @@ _Jv_ClassReader::handleClassBegin
        throw_no_class_def_found_error ("loading java.lang.Object");
     }
 
-  // In the pre-loading state, it can be looked up in the
-  // cache only by this thread!  This allows the super-class
-  // to include references to this class.
-
   def->state = JV_STATE_PRELOADING;
 
-  {
-    JvSynchronize sync (&java::lang::Class::class$);
-    _Jv_RegisterClass (def);
-  }
+  // Register this class with its defining loader as well (despite the
+  // name of the function we're calling), so that super class lookups
+  // work properly.  If there is an error, our caller will unregister
+  // this class from the class loader.  Also, we don't need to hold a
+  // lock here, as our caller has acquired it.
+  _Jv_RegisterInitiatingLoader (def, def->loader);
 
   if (super_class != 0)
     {
@@ -943,23 +977,25 @@ _Jv_ClassReader::handleClassBegin
   def->notifyAll ();
 }
 
-///// implements the checks described in sect. 5.3.5.3
+///// Implements the checks described in sect. 5.3.5.3
 void
 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
 {
   using namespace java::lang::reflect;
 
-  // having an interface or a final class as a superclass is no good
+  _Jv_Linker::wait_for_state (super, JV_STATE_LOADING);
+
+  // Having an interface or a final class as a superclass is no good.
   if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
     {
       throw_incompatible_class_change_error (sub->getName ());
     }
 
-  // if the super class is not public, we need to check some more
+  // If the super class is not public, we need to check some more.
   if ((super->accflags & Modifier::PUBLIC) == 0)
     {
-      // With package scope, the classes must have the same
-      // class loader.
+      // With package scope, the classes must have the same class
+      // loader.
       if (   sub->loader != super->loader
          || !_Jv_ClassNameSamePackage (sub->name, super->name))
        {
@@ -967,7 +1003,7 @@ _Jv_ClassReader::checkExtends (jclass sub, jclass super)
        }
     } 
 
-  for (; super != 0; super = super->superclass)
+  for (; super != 0; super = super->getSuperclass ())
     {
       if (super == sub)
        throw_class_circularity_error (sub->getName ());
@@ -1047,10 +1083,10 @@ void _Jv_ClassReader::handleFieldsBegin (int count)
   def->fields = (_Jv_Field*) 
     _Jv_AllocBytes (count * sizeof (_Jv_Field));
   def->field_count = count;
-  def->field_initializers = (_Jv_ushort*)
+  def_interp->field_initializers = (_Jv_ushort*)
     _Jv_AllocBytes (count * sizeof (_Jv_ushort));
   for (int i = 0; i < count; i++)
-    def->field_initializers[i] = (_Jv_ushort) 0;
+    def_interp->field_initializers[i] = (_Jv_ushort) 0;
 }
 
 void _Jv_ClassReader::handleField (int field_no,
@@ -1065,36 +1101,40 @@ void _Jv_ClassReader::handleField (int field_no,
   _Jv_Field *field = &def->fields[field_no];
   _Jv_Utf8Const *field_name = pool_data[name].utf8;
 
-#ifndef COMPACT_FIELDS
   field->name      = field_name;
-#else
-  field->nameIndex = name;
-#endif
 
-  if (verify)
-    verify_identifier (field_name);
-
-  // ignore flags we don't know about.  
+  // Ignore flags we don't know about.  
   field->flags = flags & Modifier::ALL_FLAGS;
 
+  _Jv_Utf8Const* sig = pool_data[desc].utf8;
+
   if (verify)
     {
-      if (field->flags & (Modifier::SYNCHRONIZED
-                         | Modifier::NATIVE
-                         | Modifier::INTERFACE
-                         | Modifier::ABSTRACT))
-       throw_class_format_error ("erroneous field access flags");
-      
+      verify_identifier (field_name);
+
+      for (int i = 0; i < field_no; ++i)
+       {
+         if (_Jv_equalUtf8Consts (field_name, def->fields[i].name)
+             && _Jv_equalUtf8Consts (sig,
+                                     // We know the other fields are
+                                     // unresolved.
+                                     (_Jv_Utf8Const *) def->fields[i].type))
+           throw_class_format_error ("duplicate field name");
+       }
+
+      // At most one of PUBLIC, PRIVATE, or PROTECTED is allowed.
       if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
                +((field->flags & Modifier::PRIVATE) ? 1 : 0)
                +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
        throw_class_format_error ("erroneous field access flags");
-    }
 
-  _Jv_Utf8Const* sig = pool_data[desc].utf8;
+      // FIXME: JVM spec S4.5: Verify ACC_FINAL and ACC_VOLATILE are not 
+      // both set. Verify modifiers for interface fields.
+      
+    }
 
   if (verify)
-    _Jv_VerifyFieldSignature (sig);
+    verify_field_signature (sig);
 
   // field->type is really a jclass, but while it is still
   // unresolved we keep an _Jv_Utf8Const* instead.
@@ -1124,7 +1164,7 @@ void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
     throw_class_format_error ("field has multiple ConstantValue attributes");
 
   field->flags |= _Jv_FIELD_CONSTANT_VALUE;
-  def->field_initializers[field_index] = value;
+  def_interp->field_initializers[field_index] = value;
 
   /* type check the initializer */
   
@@ -1144,7 +1184,7 @@ void _Jv_ClassReader::handleFieldsEnd ()
   int low            = 0;
   int high           = def->field_count-1;
   _Jv_Field  *fields = def->fields;
-  _Jv_ushort *inits  = def->field_initializers;
+  _Jv_ushort *inits  = def_interp->field_initializers;
 
   // this is kind of a raw version of quicksort.
   while (low < high)
@@ -1186,13 +1226,13 @@ _Jv_ClassReader::handleMethodsBegin (int count)
 {
   def->methods = (_Jv_Method *) _Jv_AllocBytes (sizeof (_Jv_Method) * count);
 
-  def->interpreted_methods
+  def_interp->interpreted_methods
     = (_Jv_MethodBase **) _Jv_AllocBytes (sizeof (_Jv_MethodBase *)
                                          * count);
 
   for (int i = 0; i < count; i++)
     {
-      def->interpreted_methods[i] = 0;
+      def_interp->interpreted_methods[i] = 0;
       def->methods[i].index = (_Jv_ushort) -1;
     }
 
@@ -1219,7 +1259,7 @@ void _Jv_ClassReader::handleMethod
   // ignore unknown flags
   method->accflags = accflags & Modifier::ALL_FLAGS;
 
-  // intialize...
+  // Initialize...
   method->ncode = 0;
   method->throws = NULL;
   
@@ -1231,17 +1271,25 @@ void _Jv_ClassReader::handleMethod
       else
        verify_identifier (method->name);
 
-      _Jv_VerifyMethodSignature (method->signature);
+      verify_method_signature (method->signature);
 
-      if (method->accflags & (Modifier::VOLATILE
-                             | Modifier::TRANSIENT
-                             | Modifier::INTERFACE))
-       throw_class_format_error ("erroneous method access flags");
-      
+      for (int i = 0; i < mth_index; ++i)
+       {
+         if (_Jv_equalUtf8Consts (method->name, def->methods[i].name)
+             && _Jv_equalUtf8Consts (method->signature,
+                                     def->methods[i].signature))
+           throw_class_format_error ("duplicate method");
+       }
+
+      // At most one of PUBLIC, PRIVATE, or PROTECTED is allowed.
       if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
                +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
                +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
        throw_class_format_error ("erroneous method access flags");
+
+      // FIXME: JVM spec S4.6: if ABSTRACT modifier is set, verify other 
+      // flags are not set. Verify flags for interface methods. Verifiy
+      // modifiers for initializers. 
     }
 }
 
@@ -1260,13 +1308,25 @@ void _Jv_ClassReader::handleCodeAttribute
   method->defining_class = def;
   method->self           = &def->methods[method_index];
   method->prepared       = NULL;
+  method->line_table_len = 0;
+  method->line_table     = NULL;
+
 
   // grab the byte code!
   memcpy ((void*) method->bytecode (),
          (void*) (bytes+code_start),
          code_length);
 
-  def->interpreted_methods[method_index] = method;
+  def_interp->interpreted_methods[method_index] = method;
+
+  if ((method->self->accflags & java::lang::reflect::Modifier::STATIC))
+    {
+      // Precompute the ncode field for a static method.  This lets us
+      // call a static method of an interpreted class from precompiled
+      // code without first resolving the class (that will happen
+      // during class initialization instead).
+      method->self->ncode = method->ncode ();
+    }
 }
 
 void _Jv_ClassReader::handleExceptionTableEntry
@@ -1274,7 +1334,7 @@ void _Jv_ClassReader::handleExceptionTableEntry
    int start_pc, int end_pc, int handler_pc, int catch_type)
 {
   _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
-    (def->interpreted_methods[method_index]);
+    (def_interp->interpreted_methods[method_index]);
   _Jv_InterpException *exc = method->exceptions ();
 
   exc[exc_index].start_pc.i     = start_pc;
@@ -1292,7 +1352,7 @@ void _Jv_ClassReader::handleMethodsEnd ()
       _Jv_Method *method = &def->methods[i];
       if ((method->accflags & Modifier::NATIVE) != 0)
        {
-         if (def->interpreted_methods[i] != 0)
+         if (def_interp->interpreted_methods[i] != 0)
            throw_class_format_error ("code provided for native method");
          else
            {
@@ -1301,17 +1361,27 @@ void _Jv_ClassReader::handleMethodsEnd ()
              m->defining_class = def;
              m->self = method;
              m->function = NULL;
-             def->interpreted_methods[i] = m;
+             def_interp->interpreted_methods[i] = m;
+
+             if ((method->accflags & Modifier::STATIC))
+               {
+                 // Precompute the ncode field for a static method.
+                 // This lets us call a static method of an
+                 // interpreted class from precompiled code without
+                 // first resolving the class (that will happen
+                 // during class initialization instead).
+                 method->ncode = m->ncode ();
+               }
            }
        }
       else if ((method->accflags & Modifier::ABSTRACT) != 0)
        {
-         if (def->interpreted_methods[i] != 0)
+         if (def_interp->interpreted_methods[i] != 0)
            throw_class_format_error ("code provided for abstract method");
        }
       else
        {
-         if (def->interpreted_methods[i] == 0)
+         if (def_interp->interpreted_methods[i] == 0)
            throw_class_format_error ("method with no code");
        }
     }
@@ -1323,8 +1393,8 @@ void _Jv_ClassReader::throw_class_format_error (char *msg)
   if (def->name != NULL)
     {
       jsize mlen = strlen (msg);
-      unsigned char* data = (unsigned char*) def->name->data;
-      int ulen = def->name->length;
+      unsigned char* data = (unsigned char*) def->name->chars();
+      int ulen = def->name->len();
       unsigned char* limit = data + ulen;
       jsize nlen = _Jv_strLengthUtf8 ((char *) data, ulen);
       jsize len = nlen + mlen + 3;
@@ -1456,8 +1526,8 @@ _Jv_VerifyOne (unsigned char* ptr, unsigned char* limit, bool void_ok)
 bool
 _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig)
 {
-  unsigned char* ptr = (unsigned char*) sig->data;
-  unsigned char* limit = ptr + sig->length;
+  unsigned char* ptr = (unsigned char*) sig->chars();
+  unsigned char* limit = ptr + sig->len();
 
   ptr = _Jv_VerifyOne (ptr, limit, false);
 
@@ -1467,8 +1537,8 @@ _Jv_VerifyFieldSignature (_Jv_Utf8Const*sig)
 bool
 _Jv_VerifyMethodSignature (_Jv_Utf8Const*sig)
 {
-  unsigned char* ptr = (unsigned char*) sig->data;
-  unsigned char* limit = ptr + sig->length;
+  unsigned char* ptr = (unsigned char*) sig->chars();
+  unsigned char* limit = ptr + sig->len();
 
   if (ptr == limit || UTF8_GET(ptr,limit) != '(')
     return false;
@@ -1522,8 +1592,8 @@ is_identifier_part (int c)
 bool
 _Jv_VerifyIdentifier (_Jv_Utf8Const* name)
 {
-  unsigned char *ptr   = (unsigned char*) name->data;
-  unsigned char *limit = ptr + name->length;
+  unsigned char *ptr   = (unsigned char*) name->chars();
+  unsigned char *limit = (unsigned char*) name->limit();
   int ch;
 
   if ((ch = UTF8_GET (ptr, limit))==-1
@@ -1578,17 +1648,16 @@ _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
 bool
 _Jv_VerifyClassName (_Jv_Utf8Const *name)
 {
-  return _Jv_VerifyClassName ((unsigned char*)&name->data[0],
-                             (_Jv_ushort) name->length);
+  return _Jv_VerifyClassName ((unsigned char*)name->chars(), name->len());
 }
 
 /* Returns true, if NAME1 and NAME2 represent classes in the same
-   package.  */
+   package.  Neither NAME2 nor NAME2 may name an array type.  */
 bool
 _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
 {
-  unsigned char* ptr1 = (unsigned char*) name1->data;
-  unsigned char* limit1 = ptr1 + name1->length;
+  unsigned char* ptr1 = (unsigned char*) name1->chars();
+  unsigned char* limit1 = (unsigned char*) name1->limit();
 
   unsigned char* last1 = ptr1;
 
@@ -1604,20 +1673,19 @@ _Jv_ClassNameSamePackage (_Jv_Utf8Const *name1, _Jv_Utf8Const *name2)
   }
 
   // Now the length of NAME1's package name is LEN.
-  int len = last1 - (unsigned char*) name1->data;
+  int len = last1 - (unsigned char*) name1->chars();
 
   // If this is longer than NAME2, then we're off.
-  if (len > name2->length)
+  if (len > name2->len())
     return false;
 
   // Then compare the first len bytes for equality.
-  if (memcmp ((void*) name1->data, (void*) name2->data, len) == 0)
+  if (memcmp ((void*) name1->chars(), (void*) name2->chars(), len) == 0)
     {
       // Check that there are no .'s after position LEN in NAME2.
 
-      unsigned char* ptr2 = (unsigned char*) name2->data + len;
-      unsigned char* limit2 =
-       (unsigned char*) name2->data + name2->length;
+      unsigned char* ptr2 = (unsigned char*) name2->chars() + len;
+      unsigned char* limit2 = (unsigned char*) name2->limit();
 
       while (ptr2 < limit2)
        {