diff --git a/libjava/ChangeLog b/libjava/ChangeLog
index 52e79eba376547d2dce19c15c4121d65f00eb640..6411c2a9692dc11e341e675dae99958bf70ac1d5 100644
--- a/libjava/ChangeLog
+++ b/libjava/ChangeLog
@@ -1,3 +1,15 @@
+2005-04-05  Tom Tromey  <tromey@redhat.com>
+
+	* jni.cc (_Jv_JNI_GetAnyFieldID): Throw ClassNotFoundException.
+	* java/lang/reflect/natMethod.cc (_Jv_GetTypesFromSignature):
+	Rewrote to use _Jv_FindClassFromSignature.
+	* verify.cc (resolve): throw NoClassDefFoundError.
+	* link.cc (resolve_field): Throw NoClassDefFoundError.
+	(find_field): Likewise.
+	* prims.cc (_Jv_FindClassFromSignature): Removed recursion.
+	Handle error cases.  Added 'endp' argument.
+	* include/jvm.h (_Jv_FindClassFromSignature): Updated prototype.
+
 2005-04-05  Tom Tromey  <tromey@redhat.com>
 
 	* Makefile.in: Rebuilt.
diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h
index a95b7124aa853423bd25db6f6d6f03925fac52bf..bbc809bc162253596945d382ec82e1cd6af230ae 100644
--- a/libjava/include/jvm.h
+++ b/libjava/include/jvm.h
@@ -448,7 +448,8 @@ extern void _Jv_UnregisterClass (_Jv_Utf8Const*, java::lang::ClassLoader*);
 extern jclass _Jv_FindClass (_Jv_Utf8Const *name,
 			     java::lang::ClassLoader *loader);
 extern jclass _Jv_FindClassFromSignature (char *,
-					  java::lang::ClassLoader *loader);
+					  java::lang::ClassLoader *loader,
+					  char ** = NULL);
 extern void _Jv_GetTypesFromSignature (jmethodID method,
 				       jclass declaringClass,
 				       JArray<jclass> **arg_types_out,
diff --git a/libjava/java/lang/natClassLoader.cc b/libjava/java/lang/natClassLoader.cc
index 00292f93dad5836ca6c3d9bb4567002c0b57d8a4..b8d87c6062bc3cd4fda15b441be1678091554834 100644
--- a/libjava/java/lang/natClassLoader.cc
+++ b/libjava/java/lang/natClassLoader.cc
@@ -252,27 +252,30 @@ _Jv_FindClass (_Jv_Utf8Const *name, java::lang::ClassLoader *loader)
 	  // Not even a bootstrap loader, try the built-in cache.
 	  klass = _Jv_FindClassInCache (name);
 
-	  bool found = false;
-	  for (int i = 0; i < bootstrap_index; ++i)
+	  if (klass)
 	    {
-	      if (bootstrap_class_list[i] == klass)
+	      bool found = false;
+	      for (int i = 0; i < bootstrap_index; ++i)
 		{
-		  found = true;
-		  break;
+		  if (bootstrap_class_list[i] == klass)
+		    {
+		      found = true;
+		      break;
+		    }
+		}
+	      if (! found)
+		{
+		  if (bootstrap_index == BOOTSTRAP_CLASS_LIST_SIZE)
+		    abort ();
+		  bootstrap_class_list[bootstrap_index++] = klass;
 		}
-	    }
-	  if (! found)
-	    {
-	      if (bootstrap_index == BOOTSTRAP_CLASS_LIST_SIZE)
-		abort ();
-	      bootstrap_class_list[bootstrap_index++] = klass;
 	    }
 	}
     }
   else
     {
-      // we need classes to be in the hash while
-      // we're loading, so that they can refer to themselves. 
+      // We need classes to be in the hash while we're loading, so
+      // that they can refer to themselves.
       _Jv_Linker::wait_for_state (klass, JV_STATE_LOADED);
     }
 
diff --git a/libjava/java/lang/natVMClassLoader.cc b/libjava/java/lang/natVMClassLoader.cc
index e6c3b947d2428d31d1028181ea87a5488c61b147..182b8d72743b01a26e6ac1e31e4e3ffcacac4ccd 100644
--- a/libjava/java/lang/natVMClassLoader.cc
+++ b/libjava/java/lang/natVMClassLoader.cc
@@ -123,6 +123,7 @@ java::lang::VMClassLoader::getPrimitiveClass (jchar type)
   char sig[2];
   sig[0] = (char) type;
   sig[1] = '\0';
+  // Note: this cannot return NULL, since the input is always correct.
   return _Jv_FindClassFromSignature (sig, NULL);
 }
 
diff --git a/libjava/java/lang/reflect/natMethod.cc b/libjava/java/lang/reflect/natMethod.cc
index 4329443146cd270dd685e4fac77ec8bbd4361b70..b616d1bab63508739254c29f1741ff66a1790a60 100644
--- a/libjava/java/lang/reflect/natMethod.cc
+++ b/libjava/java/lang/reflect/natMethod.cc
@@ -38,6 +38,7 @@ details.  */
 #include <java/lang/Class.h>
 #include <gcj/method.h>
 #include <gnu/gcj/RawData.h>
+#include <java/lang/NoClassDefFoundError.h>
 
 #include <stdlib.h>
 
@@ -235,6 +236,8 @@ _Jv_GetTypesFromSignature (jmethodID method,
   char *ptr = sig->chars();
   int numArgs = 0;
   /* First just count the number of parameters. */
+  // FIXME: should do some validation here, e.g., that there is only
+  // one return type.
   for (; ; ptr++)
     {
       switch (*ptr)
@@ -271,44 +274,26 @@ _Jv_GetTypesFromSignature (jmethodID method,
   jclass* argPtr = elements (args);
   for (ptr = sig->chars(); *ptr != '\0'; ptr++)
     {
-      int num_arrays = 0;
-      jclass type;
-      for (; *ptr == '[';  ptr++)
-	num_arrays++;
-      switch (*ptr)
+      if (*ptr == '(')
+	continue;
+      if (*ptr == ')')
 	{
-	default:
-	  return;
-	case ')':
 	  argPtr = return_type_out;
 	  continue;
-	case '(':
-	  continue;
-	case 'V':
-	case 'B':
-	case 'C':
-	case 'D':
-	case 'F':
-	case 'S':
-	case 'I':
-	case 'J':
-	case 'Z':
-	  type = _Jv_FindClassFromSignature(ptr, loader);
-	  break;
-	case 'L':
-	  type = _Jv_FindClassFromSignature(ptr, loader);
-	  do 
-	    ptr++;
-	  while (*ptr != ';' && ptr[1] != '\0');
-	  break;
 	}
 
-      while (--num_arrays >= 0)
-	type = _Jv_GetArrayClass (type, loader);
+      char *end_ptr;
+      jclass type = _Jv_FindClassFromSignature (ptr, loader, &end_ptr);
+      if (type == NULL)
+	// FIXME: This isn't ideal.
+	throw new java::lang::NoClassDefFoundError (sig->toString());
+
       // ARGPTR can be NULL if we are processing the return value of a
       // call from Constructor.
       if (argPtr)
 	*argPtr++ = type;
+
+      ptr = end_ptr;
     }
   *arg_types_out = args;
 }
diff --git a/libjava/jni.cc b/libjava/jni.cc
index 5f9d5f79e719d50fba1d0b4df97d6382554251ee..b68c3bb887f0533511e37a62b0d63c6261163a10 100644
--- a/libjava/jni.cc
+++ b/libjava/jni.cc
@@ -46,6 +46,7 @@ details.  */
 #include <java/nio/DirectByteBufferImpl$ReadWrite.h>
 #include <java/util/IdentityHashMap.h>
 #include <gnu/gcj/RawData.h>
+#include <java/lang/ClassNotFoundException.h>
 
 #include <gcj/method.h>
 #include <gcj/field.h>
@@ -1200,8 +1201,8 @@ _Jv_JNI_GetAnyFieldID (JNIEnv *env, jclass clazz,
       for (int i = 0; i <= len; ++i)
 	s[i] = (sig[i] == '/') ? '.' : sig[i];
       jclass field_class = _Jv_FindClassFromSignature ((char *) s, NULL);
-
-      // FIXME: what if field_class == NULL?
+      if (! field_class)
+	throw new java::lang::ClassNotFoundException(JvNewStringUTF(s));
 
       java::lang::ClassLoader *loader = clazz->getClassLoaderInternal ();
       while (clazz != NULL)
diff --git a/libjava/link.cc b/libjava/link.cc
index 909a7b68a0e972f52fed33c3421c183adaee04f8..176b538d64a9db04b4c9d94bba22af82868d069f 100644
--- a/libjava/link.cc
+++ b/libjava/link.cc
@@ -90,8 +90,11 @@ _Jv_Linker::resolve_field (_Jv_Field *field, java::lang::ClassLoader *loader)
 {
   if (! field->isResolved ())
     {
-      _Jv_Utf8Const *sig = (_Jv_Utf8Const*)field->type;
-      field->type = _Jv_FindClassFromSignature (sig->chars(), loader);
+      _Jv_Utf8Const *sig = (_Jv_Utf8Const *) field->type;
+      jclass type = _Jv_FindClassFromSignature (sig->chars(), loader);
+      if (type == NULL)
+	throw new java::lang::NoClassDefFoundError(field->name->toString());
+      field->type = type;
       field->flags &= ~_Jv_FIELD_UNRESOLVED_FLAG;
     }
 }
@@ -174,6 +177,8 @@ _Jv_Linker::find_field (jclass klass, jclass owner,
   // it cheaper.
   jclass field_type = _Jv_FindClassFromSignature (field_type_name->chars(),
 						  klass->loader);
+  if (field_type == NULL)
+    throw new java::lang::NoClassDefFoundError(field_name->toString());
 
   jclass found_class = 0;
   _Jv_Field *the_field = find_field_helper (owner, field_name,
diff --git a/libjava/prims.cc b/libjava/prims.cc
index 7060171223819cdfdf14d1e62e595681d77996ab..fadc466bc0e9d3623e1ebbc6200a5990710b858d 100644
--- a/libjava/prims.cc
+++ b/libjava/prims.cc
@@ -675,46 +675,79 @@ _Jv_InitPrimClass (jclass cl, char *cname, char sig, int len)
 }
 
 jclass
-_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader)
+_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader,
+			    char **endp)
 {
+  // First count arrays.
+  int array_count = 0;
+  while (*sig == '[')
+    {
+      ++sig;
+      ++array_count;
+    }
+
+  jclass result = NULL;
   switch (*sig)
     {
     case 'B':
-      return JvPrimClass (byte);
+      result = JvPrimClass (byte);
+      break;
     case 'S':
-      return JvPrimClass (short);
+      result = JvPrimClass (short);
+      break;
     case 'I':
-      return JvPrimClass (int);
+      result = JvPrimClass (int);
+      break;
     case 'J':
-      return JvPrimClass (long);
+      result = JvPrimClass (long);
+      break;
     case 'Z':
-      return JvPrimClass (boolean);
+      result = JvPrimClass (boolean);
+      break;
     case 'C':
-      return JvPrimClass (char);
+      result = JvPrimClass (char);
+      break;
     case 'F':
-      return JvPrimClass (float);
+      result = JvPrimClass (float);
+      break;
     case 'D':
-      return JvPrimClass (double);
+      result = JvPrimClass (double);
+      break;
     case 'V':
-      return JvPrimClass (void);
+      result = JvPrimClass (void);
+      break;
     case 'L':
       {
-	int i;
-	for (i = 1; sig[i] && sig[i] != ';'; ++i)
-	  ;
-	_Jv_Utf8Const *name = _Jv_makeUtf8Const (&sig[1], i - 1);
-	return _Jv_FindClass (name, loader);
-      }
-    case '[':
-      {
-	jclass klass = _Jv_FindClassFromSignature (&sig[1], loader);
-	if (! klass)
-	  return NULL;
-	return _Jv_GetArrayClass (klass, loader);
+	char *save = ++sig;
+	while (*sig && *sig != ';')
+	  ++sig;
+	// Do nothing if signature appears to be malformed.
+	if (*sig == ';')
+	  {
+	    _Jv_Utf8Const *name = _Jv_makeUtf8Const (save, sig - save);
+	    result = _Jv_FindClass (name, loader);
+	  }
+	break;
       }
+    default:
+      // Do nothing -- bad signature.
+      break;
     }
 
-  return NULL;			// Placate compiler.
+  if (endp)
+    {
+      // Not really the "end", but the last valid character that we
+      // looked at.
+      *endp = sig;
+    }
+
+  if (! result)
+    return NULL;
+
+  // Find arrays.
+  while (array_count-- > 0)
+    result = _Jv_GetArrayClass (result, loader);
+  return result;
 }
 
 
diff --git a/libjava/verify.cc b/libjava/verify.cc
index 141f27af7970cd5c7f94e18f10e0e909e5d48179..a47571bb809e9c8e5073473f4d1537250aa874f4 100644
--- a/libjava/verify.cc
+++ b/libjava/verify.cc
@@ -31,6 +31,7 @@ details.  */
 #include <java/lang/Throwable.h>
 #include <java/lang/reflect/Modifier.h>
 #include <java/lang/StringBuffer.h>
+#include <java/lang/NoClassDefFoundError.h>
 
 #ifdef VERIFY_DEBUG
 #include <stdio.h>
@@ -368,7 +369,11 @@ private:
 	= verifier->current_class->getClassLoaderInternal();
       // We might see either kind of name.  Sigh.
       if (data.name->first() == 'L' && data.name->limit()[-1] == ';')
-	data.klass = _Jv_FindClassFromSignature (data.name->chars(), loader);
+	{
+	  data.klass = _Jv_FindClassFromSignature (data.name->chars(), loader);
+	  if (data.klass == NULL)
+	    throw new java::lang::NoClassDefFoundError(data.name->toString());
+	}
       else
 	data.klass = Class::forName (_Jv_NewStringUtf8Const (data.name),
 				     false, loader);