This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Stack traces, etc.
- From: Andrew Haley <aph at redhat dot com>
- To: Mark Wielaard <mark at klomp dot org>
- Cc: java at gcc dot gnu dot org
- Date: Mon, 2 Dec 2002 20:27:21 +0000 (GMT)
- Subject: Re: Stack traces, etc.
- References: <15847.65022.630354.996182@cuddles.cambridge.redhat.com><1038651258.12096.128.camel@elsschot><15848.39333.183099.838746@cuddles.cambridge.redhat.com><1038758828.12098.189.camel@elsschot>
Revised, VMThrowable reinstated, testing now. Checkin tomorrow unless
anyone complains.
Andrew.
2002-11-29 Andrew Haley <aph@redhat.com>
* java/lang/natClassLoader.cc (_Jv_PrepareCompiledClass): Call _Jv_PushClass.
(_Jv_InitNewClassFields): Set protectionDomain and chain = NULL.
(_Jv_PopClass): New.
(_Jv_PushClass): New.
* java/lang/natClass.cc (forName (jstring)): Use a StackTrace to
discover the ClassLoader of our caller.
(_Jv_CheckArrayStore): Don't check that a class is assignment
compatible with Object.
* gnu/gcj/runtime/StackTrace.java: Renamed from java.lang.VMThrowable.
(StackTrace(), StackTrace(int)): New constructors.
(classAt, methodAt, update, methodAtAddress): New methods.
(map): New field.
* java/lang/Throwable.java (fillInStackTrace): Call StackTrace to
get the stack trace.
(Throwable.vmState): Now an instance of StackTrace.
* java/lang/Class.h (getClassLoaderInternal): New.
(class Class): Be friendly with _Jv_PopClass and _Jv_PushClass.
Be friendly with gnu::gcj::runtime::StackTrace.
(Object.chain): New field.
* include/java-interp.h (class _Jv_InterpMethod): Be friendly with
gnu::gcj::runtime::StackTrace.
* gnu/gcj/runtime/NameFinder.java (sanitizeStack): Use
gnu::gcj::runtime::StackTrace, not java::lang::VMThrowable.
* gcj/javaprims.h ("Java"): Remove class java.lang.VMThrowable.
* prims.cc (_Jv_NewObjectArray): Use getClassLoaderInternal()
instead of getClassLoader().
* verify.cc (class _Jv_BytecodeVerifier): Likewise.
(_Jv_CreateJavaVM): Use gnu::gcj::runtime::StackTrace, not
java::lang::VMThrowable.
* Makefile.am (core_java_source_files): Remove VMThrowable.java.
(ordinary_java_source_files): Add MethodRef.java, StackTrace.java.
(nat_source_files): Remove natVMThrowable.cc; add natStackTrace.cc.
* Makefile.in: Rebuild.
Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.261
diff -w -p -2 -c -r1.261 Makefile.am
*** Makefile.am 21 Nov 2002 10:45:12 -0000 1.261
--- Makefile.am 2 Dec 2002 20:23:07 -0000
*************** gnu/gcj/runtime/FinalizerThread.java \
*** 1721,1726 ****
--- 1721,1728 ----
gnu/gcj/runtime/FirstThread.java \
gnu/gcj/runtime/JNIWeakRef.java \
+ gnu/gcj/runtime/MethodRef.java \
gnu/gcj/runtime/NameFinder.java \
gnu/gcj/runtime/SharedLibLoader.java \
+ gnu/gcj/runtime/StackTrace.java \
gnu/gcj/runtime/StringBuffer.java \
gnu/gcj/runtime/VMClassLoader.java \
*************** gnu/gcj/runtime/natFirstThread.cc \
*** 2317,2320 ****
--- 2319,2323 ----
gnu/gcj/runtime/natNameFinder.cc \
gnu/gcj/runtime/natSharedLibLoader.cc \
+ gnu/gcj/runtime/natStackTrace.cc \
gnu/gcj/runtime/natStringBuffer.cc \
java/io/natFile.cc \
*************** java/lang/natStringBuffer.cc \
*** 2335,2339 ****
java/lang/natSystem.cc \
java/lang/natThread.cc \
- java/lang/natVMThrowable.cc \
java/lang/ref/natReference.cc \
java/lang/reflect/natArray.cc \
--- 2338,2341 ----
Index: prims.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/prims.cc,v
retrieving revision 1.74
diff -w -p -2 -c -r1.74 prims.cc
*** prims.cc 2 Nov 2002 21:33:30 -0000 1.74
--- prims.cc 2 Dec 2002 20:23:10 -0000
*************** _Jv_NewObjectArray (jsize count, jclass
*** 459,464 ****
size += count * sizeof (jobject);
! // FIXME: second argument should be "current loader"
! jclass klass = _Jv_GetArrayClass (elementClass, 0);
obj = (jobjectArray) _Jv_AllocArray (size, klass);
--- 459,464 ----
size += count * sizeof (jobject);
! jclass klass = _Jv_GetArrayClass (elementClass,
! elementClass->getClassLoaderInternal());
obj = (jobjectArray) _Jv_AllocArray (size, klass);
Index: verify.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/verify.cc,v
retrieving revision 1.45
diff -w -p -2 -c -r1.45 verify.cc
*** verify.cc 27 Nov 2002 05:59:39 -0000 1.45
--- verify.cc 2 Dec 2002 20:23:11 -0000
*************** private:
*** 406,410 ****
using namespace java::lang;
java::lang::ClassLoader *loader
! = verifier->current_class->getClassLoader();
// We might see either kind of name. Sigh.
if (data.name->data[0] == 'L'
--- 406,410 ----
using namespace java::lang;
java::lang::ClassLoader *loader
! = verifier->current_class->getClassLoaderInternal();
// We might see either kind of name. Sigh.
if (data.name->data[0] == 'L'
*************** private:
*** 572,576 ****
if (key == reference_type)
return type (_Jv_GetArrayClass (data.klass,
! data.klass->getClassLoader ()));
else
verifier->verify_fail ("internal error in type::to_array()");
--- 572,576 ----
if (key == reference_type)
return type (_Jv_GetArrayClass (data.klass,
! data.klass->getClassLoaderInternal()));
else
verifier->verify_fail ("internal error in type::to_array()");
*************** private:
*** 696,700 ****
{
java::lang::ClassLoader *loader
! = verifier->current_class->getClassLoader();
k = _Jv_GetArrayClass (k, loader);
--arraycount;
--- 696,700 ----
{
java::lang::ClassLoader *loader
! = verifier->current_class->getClassLoaderInternal();
k = _Jv_GetArrayClass (k, loader);
--arraycount;
Index: gnu/gcj/runtime/MethodRef.java
===================================================================
RCS file: gnu/gcj/runtime/MethodRef.java
diff -N gnu/gcj/runtime/MethodRef.java
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gnu/gcj/runtime/MethodRef.java 2 Dec 2002 20:23:11 -0000
***************
*** 0 ****
--- 1,25 ----
+ // gnu.gcj.runtime.MethodRef -- used by StackTrace.
+
+ /* Copyright (C) 2002 Free Software Foundation
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+ package gnu.gcj.runtime;
+
+ import gnu.gcj.RawData;
+
+ class MethodRef
+ {
+ MethodRef(RawData /* Actually _Jv_Method */ m, Class k)
+ {
+ klass = k;
+ method = m;
+ }
+
+ public RawData method; // Actually a raw pointer to _Jv_Method
+ public Class klass;
+ }
Index: gnu/gcj/runtime/StackTrace.java
===================================================================
RCS file: gnu/gcj/runtime/StackTrace.java
diff -N gnu/gcj/runtime/StackTrace.java
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gnu/gcj/runtime/StackTrace.java 2 Dec 2002 20:23:11 -0000
***************
*** 0 ****
--- 1,164 ----
+ /* gnu.gcj.runtime.StackTrace -- VM support methods for walking the
+ stack.
+ Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
+
+ package gnu.gcj.runtime;
+
+ import gnu.gcj.RawData;
+ import java.util.TreeMap;
+ import java.util.IdentityHashMap;
+ import java.util.SortedMap;
+ import gnu.gcj.runtime.NameFinder;
+ import java.util.NoSuchElementException;
+
+ /**
+ * VM dependent state and support methods for walking the stack.
+ * <p>
+ * This is the version used by libgcj (http://gcc.gnu.org/java/).
+ *
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Andrew Haley (aph@redhat.com)
+ */
+ public final class StackTrace
+ {
+ /**
+ * Fill in the stack trace with the top n frames on current
+ * execution stack. Can return null if the VM does not support
+ * capturing the VM execution state.
+ *
+ * @see Throwable#fillInStackTrace()
+ */
+ public StackTrace(int n)
+ {
+ fillInStackTrace(n, 1);
+ }
+
+ /**
+ * Fill in the stack trace with state of the entire execution stack,
+ * starting from frame <code>offset</code>. Can return null if the
+ * VM does not support capturing the VM execution state.
+ *
+ * This can be very expensive. If you only want part of the stack,
+ * see <code>Throwable.fillInStackTrace(int)</code>
+ *
+ * @see Throwable#fillInStackTrace()
+ */
+ public StackTrace()
+ {
+ int n = 64;
+
+ do
+ {
+ n *= 4;
+ fillInStackTrace(n, 1);
+ }
+ while (len >= n);
+ }
+
+ /**
+ * Return the class containing the execution point represented by
+ * the Nth frame down the stack. The zeroth frame represents the
+ * top of the stack, which is the method that called classAt().
+ *
+ * If the Nth frame down the stack was not create by a method
+ * invocation, return null.
+ *
+ * It is not necessary to call <code>fillInStackTrace()</code> with
+ * a size greater than N before calling this method; if the current
+ * stack trace is insufficiently large, it will be expanded as
+ * required. This requires some caution if
+ * <code>fillInStackTrace()</code> is called from a different
+ * invocation to the one that calls <code>classAt()</code>.
+ * classAt() will not call <code>fillInStackTrace()</code> unless N
+ * is greater than the current length.
+ *
+ */
+ public native Class classAt(int n);
+
+ /**
+ * Return the name of the method containing the execution point
+ * represented by the Nth frame down the stack. The zeroth frame
+ * represents the top of the stack, which is the method that called
+ * classAt().
+ *
+ * If the Nth frame down the stack was not create by a method
+ * invocation, return null.
+ *
+ * It is not necessary to call <code>fillInStackTrace()</code> with
+ * a size greater than N before calling this method; if the current
+ * stack trace is insufficiently large, it will be expanded as
+ * required. This requires some caution if
+ * <code>fillInStackTrace()</code> is called from a different
+ * invocation to the one that calls <code>classAt()</code>.
+ * classAt() will not call <code>fillInStackTrace()</code> unless N
+ * is greater than the current length.
+ *
+ */
+ public native String methodAt(int n);
+
+ /**
+ * Return the length of this stack trace.
+ *
+ */
+ public int length ()
+ {
+ return len;
+ }
+
+ private static native void update();
+ private static MethodRef methodAtAddress(RawData addr)
+ {
+ update();
+ synchronized (map)
+ {
+ return (MethodRef) map.get (addr);
+ }
+ }
+
+ gnu.gcj.RawData stackTraceAddrs()
+ {
+ return addrs;
+ }
+
+ private native void fillInStackTrace(int n, int offset);
+
+ private static native MethodRef getCompiledMethodRef(RawData addr);
+ private static IdentityHashMap map = new IdentityHashMap();
+
+ private gnu.gcj.RawData addrs;
+ private int len;
+ }
Index: gnu/gcj/runtime/natStackTrace.cc
===================================================================
RCS file: gnu/gcj/runtime/natStackTrace.cc
diff -N gnu/gcj/runtime/natStackTrace.cc
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gnu/gcj/runtime/natStackTrace.cc 2 Dec 2002 20:23:11 -0000
***************
*** 0 ****
--- 1,194 ----
+ // natStackTrace.cc - native helper methods for Throwable
+
+ /* Copyright (C) 2000, 2002 Free Software Foundation, Inc
+
+ This file is part of libgcj.
+
+ This software is copyrighted work licensed under the terms of the
+ Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+ details. */
+
+ /**
+ * @author Andrew Haley <aph@cygnus.com>
+ * @author Mark Wielaard <mark@klomp.org>
+ *
+ * Native helper methods for VM specific Throwable support.
+ */
+
+ #include <config.h>
+
+ #include <string.h>
+
+ #include <jvm.h>
+ #include <gcj/cni.h>
+ #include <gnu/gcj/RawData.h>
+ #include <java/lang/Object.h>
+ #include <java-threads.h>
+ #include <gnu/gcj/runtime/MethodRef.h>
+ #include <gnu/gcj/runtime/StackTrace.h>
+ #include <java/lang/Thread.h>
+ #include <java-interp.h>
+ #include <java/util/IdentityHashMap.h>
+ #include <java/lang/ArrayIndexOutOfBoundsException.h>
+
+ #include <sys/types.h>
+
+ #include <stdlib.h>
+
+ #include <unistd.h>
+
+ #ifdef HAVE_EXECINFO_H
+ #include <execinfo.h>
+ #endif
+
+ #include <unwind.h>
+
+
+ // Fill in this stack trace with N elements starting at offset.
+ void
+ gnu::gcj::runtime::StackTrace::fillInStackTrace (jint maxlen, jint offset)
+ {
+ #if defined (HAVE_BACKTRACE)
+ offset += 1;
+ void *_p[maxlen + offset];
+ len = backtrace (_p, maxlen + offset) - offset;
+ void **p = _p + offset;
+ #endif
+ _Jv_frame_info *frame;
+ if (len > 0)
+ {
+ #ifdef INTERPRETER
+ extern void _Jv_StartOfInterpreter (void);
+ extern void _Jv_EndOfInterpreter (void);
+
+ java::lang::Thread *thread = java::lang::Thread::currentThread();
+ _Jv_MethodChain *interp_frame
+ = (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
+ : NULL);
+ #endif // INTERPRETER
+
+ frame = (_Jv_frame_info *) _Jv_Malloc (len * sizeof (_Jv_frame_info));
+ for (int n = 0; n < len; n++)
+ {
+ frame[n].addr = p[n];
+ #ifdef INTERPRETER
+ if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
+ {
+ frame[n].interp = (void *) interp_frame->self;
+ interp_frame = interp_frame->next;
+ }
+ else
+ frame[n].interp = 0;
+ #endif // INTERPRETER
+ }
+ }
+ else
+ frame = NULL;
+
+ addrs = reinterpret_cast<gnu::gcj::RawData *> (frame);
+ }
+
+ /* Obtain the next power-of-2 of some integer. */
+ static inline jint
+ nextpowerof2 (jint n)
+ {
+ n |= (n >> 1);
+ n |= (n >> 2);
+ n |= (n >> 4);
+ n |= (n >> 8);
+ n |= (n >> 16);
+ return n+1;
+ }
+
+ #define GET_FRAME(N) \
+ ({ \
+ if ((N) >= len) \
+ fillInStackTrace (nextpowerof2 (N), 1); \
+ if ((N) < 0 || (N) >= len) \
+ throw new ::java::lang::ArrayIndexOutOfBoundsException (); \
+ \
+ _Jv_frame_info *frame = (_Jv_frame_info *)addrs; \
+ &frame[N]; \
+ })
+
+ gnu::gcj::runtime::MethodRef *
+ gnu::gcj::runtime::StackTrace::getCompiledMethodRef (gnu::gcj::RawData *addr)
+ {
+ void *p = _Unwind_FindEnclosingFunction (addr);
+ return gnu::gcj::runtime::StackTrace
+ ::methodAtAddress ((gnu::gcj::RawData *)p);
+ }
+
+ java::lang::Class *
+ gnu::gcj::runtime::StackTrace::classAt (jint n)
+ {
+ _Jv_frame_info *frame = GET_FRAME (n);
+
+ #ifdef INTERPRETER
+ if (frame->interp)
+ {
+ _Jv_InterpMethod *meth
+ = reinterpret_cast<_Jv_InterpMethod *> (frame->interp);
+ return meth->defining_class;
+ }
+ #endif // INTERPRETER
+
+ gnu::gcj::runtime::MethodRef *ref
+ = getCompiledMethodRef ((gnu::gcj::RawData *)frame->addr);
+ if (ref)
+ return ref->klass;
+ else
+ return NULL;
+ }
+
+ java::lang::String*
+ gnu::gcj::runtime::StackTrace::methodAt (jint n)
+ {
+ _Jv_frame_info *frame = GET_FRAME (n);
+ _Jv_Method *meth = NULL;
+
+ #ifdef INTERPRETER
+ if (frame->interp)
+ {
+ meth
+ = reinterpret_cast<_Jv_InterpMethod *> (frame->interp)
+ ->get_method();
+ }
+ #endif // INTERPRETER
+
+ if (! meth)
+ {
+ gnu::gcj::runtime::MethodRef *ref
+ = getCompiledMethodRef ((gnu::gcj::RawData *)frame->addr);
+ if (ref)
+ meth = (_Jv_Method *)ref->method;
+ }
+
+ return meth
+ ? _Jv_NewStringUtf8Const (meth->name)
+ : NULL ;
+ }
+
+ void
+ gnu::gcj::runtime::StackTrace::update(void)
+ {
+ jclass klass;
+
+ while ((klass = _Jv_PopClass ()))
+ {
+ for (int i=0; i<klass->method_count; i++)
+ {
+ JvSynchronize sync (map);
+ _Jv_Method *meth = &(klass->methods[i]);
+ if (meth->ncode) // i.e. if p is not abstract
+ {
+ gnu::gcj::runtime::MethodRef *ref
+ = new gnu::gcj::runtime::MethodRef
+ ((gnu::gcj::RawData *)meth, klass);
+ map->put ((java::lang::Object*)(meth->ncode), ref);
+ }
+ }
+ }
+ }
+
+
Index: include/java-interp.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/include/java-interp.h,v
retrieving revision 1.18
diff -w -p -2 -c -r1.18 java-interp.h
*** include/java-interp.h 29 Aug 2002 17:53:28 -0000 1.18
--- include/java-interp.h 2 Dec 2002 20:23:12 -0000
*************** details. */
*** 22,25 ****
--- 22,26 ----
#include <java/lang/Class.h>
#include <java/lang/ClassLoader.h>
+ #include <gnu/gcj/runtime/StackTrace.h>
extern "C" {
*************** class _Jv_InterpMethod : public _Jv_Meth
*** 141,144 ****
--- 142,146 ----
friend class _Jv_BytecodeVerifier;
friend class gnu::gcj::runtime::NameFinder;
+ friend class gnu::gcj::runtime::StackTrace;
friend void _Jv_PrepareClass(jclass);
Index: java/lang/Class.h
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/Class.h,v
retrieving revision 1.50
diff -w -p -2 -c -r1.50 Class.h
*** java/lang/Class.h 4 Nov 2002 02:45:31 -0000 1.50
--- java/lang/Class.h 2 Dec 2002 20:23:12 -0000
*************** details. */
*** 21,24 ****
--- 21,25 ----
#include <java/security/ProtectionDomain.h>
#include <java/lang/Package.h>
+ #include <gnu/gcj/runtime/StackTrace.h>
// We declare these here to avoid including gcj/cni.h.
*************** public:
*** 139,142 ****
--- 140,150 ----
java::lang::ClassLoader *getClassLoader (void);
+ // This is an internal method that circumvents the usual security
+ // checks when getting the class loader.
+ java::lang::ClassLoader *getClassLoaderInternal (void)
+ {
+ return loader;
+ }
+
java::lang::reflect::Constructor *getConstructor (JArray<jclass> *);
JArray<java::lang::reflect::Constructor *> *getConstructors (void);
*************** private:
*** 297,300 ****
--- 305,310 ----
friend jclass _Jv_FindClassInCache (_Jv_Utf8Const *name,
java::lang::ClassLoader *loader);
+ friend jclass _Jv_PopClass (void);
+ friend void _Jv_PushClass (jclass k);
friend void _Jv_NewArrayClass (jclass element,
java::lang::ClassLoader *loader,
*************** private:
*** 350,353 ****
--- 360,364 ----
friend class _Jv_BytecodeVerifier;
+ friend class gnu::gcj::runtime::StackTrace;
// Chain for class pool.
*************** private:
*** 404,407 ****
--- 415,420 ----
// Security Domain to which this class belongs (or null).
java::security::ProtectionDomain *protectionDomain;
+ // Used by Jv_PopClass and _Jv_PushClass to communicate with StackTrace.
+ jclass chain;
};
Index: java/lang/VMThrowable.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/VMThrowable.java,v
retrieving revision 1.1
diff -w -p -2 -c -r1.1 VMThrowable.java
*** java/lang/VMThrowable.java 24 Aug 2002 22:46:19 -0000 1.1
--- java/lang/VMThrowable.java 2 Dec 2002 20:23:12 -0000
*************** package java.lang;
*** 39,45 ****
import gnu.gcj.runtime.NameFinder;
/**
! * VM dependant state and support methods Throwabele.
* It is deliberately package local and final and should only be accessed
* by the Throwable class.
--- 39,46 ----
import gnu.gcj.runtime.NameFinder;
+ import gnu.gcj.runtime.StackTrace;
/**
! * VM dependent state and support methods Throwable.
* It is deliberately package local and final and should only be accessed
* by the Throwable class.
*************** import gnu.gcj.runtime.NameFinder;
*** 51,56 ****
final class VMThrowable
{
! private gnu.gcj.RawData stackTraceAddrs;
! private int length;
/**
--- 52,56 ----
final class VMThrowable
{
! private gnu.gcj.runtime.StackTrace trace;
/**
*************** final class VMThrowable
*** 68,72 ****
* @see Throwable#fillInStackTrace()
*/
! static native VMThrowable fillInStackTrace(Throwable t);
/**
--- 68,85 ----
* @see Throwable#fillInStackTrace()
*/
! static VMThrowable fillInStackTrace(Throwable t)
! {
! VMThrowable state = null;
!
! /* FIXME: size of the stack trace is limited to 128 elements.
! It's undoubtedly sensible to limit the stack trace, but 128 is
! rather arbitrary. It may be better to configure this. */
! if (trace_enabled)
! {
! state = new VMThrowable ();
! state.trace = new gnu.gcj.runtime.StackTrace(128);
! }
! return state;
! }
/**
*************** final class VMThrowable
*** 81,88 ****
{
StackTraceElement[] result;
! if (stackTraceAddrs != null)
{
NameFinder nameFinder = new NameFinder();
! result = nameFinder.lookup(t, stackTraceAddrs, length);
nameFinder.close();
}
--- 94,102 ----
{
StackTraceElement[] result;
! if (trace != null)
{
NameFinder nameFinder = new NameFinder();
! result = nameFinder.lookup(t, trace.stackTraceAddrs(),
! trace.length());
nameFinder.close();
}
Index: java/lang/natClass.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClass.cc,v
retrieving revision 1.55
diff -w -p -2 -c -r1.55 natClass.cc
*** java/lang/natClass.cc 10 Nov 2002 21:07:27 -0000 1.55
--- java/lang/natClass.cc 2 Dec 2002 20:23:13 -0000
*************** details. */
*** 37,40 ****
--- 37,41 ----
#include <java/lang/IllegalArgumentException.h>
#include <java/lang/IncompatibleClassChangeError.h>
+ #include <java/lang/ArrayIndexOutOfBoundsException.h>
#include <java/lang/InstantiationException.h>
#include <java/lang/NoClassDefFoundError.h>
*************** details. */
*** 48,52 ****
--- 49,56 ----
#include <java/lang/SecurityManager.h>
#include <java/lang/StringBuffer.h>
+ #include <gnu/gcj/runtime/StackTrace.h>
#include <gcj/method.h>
+ #include <gnu/gcj/runtime/MethodRef.h>
+ #include <gnu/gcj/RawData.h>
#include <java-cpool.h>
*************** java::lang::Class::forName (jstring clas
*** 72,76 ****
throw new java::lang::ClassNotFoundException (className);
- // FIXME: should use bootstrap class loader if loader is null.
jclass klass = (buffer[0] == '['
? _Jv_FindClassFromSignature (name->data, loader)
--- 76,79 ----
*************** jclass
*** 89,94 ****
java::lang::Class::forName (jstring className)
{
! // FIXME: should use class loader from calling method.
! return forName (className, true, NULL);
}
--- 92,112 ----
java::lang::Class::forName (jstring className)
{
! java::lang::ClassLoader *loader = NULL;
! gnu::gcj::runtime::StackTrace *t
! = new gnu::gcj::runtime::StackTrace(4);
! java::lang::Class *klass = NULL;
! try
! {
! for (int i=1; !klass; i++)
! {
! klass = t->classAt (i);
! }
! loader = klass->getClassLoader();
! }
! catch (::java::lang::ArrayIndexOutOfBoundsException *e)
! {
! }
!
! return forName (className, true, loader);
}
*************** _Jv_CheckArrayStore (jobject arr, jobjec
*** 1041,1044 ****
--- 1059,1064 ----
JvAssert (arr != NULL);
jclass elt_class = (JV_CLASS (arr))->getComponentType();
+ if (elt_class == &java::lang::Object::class$)
+ return;
jclass obj_class = JV_CLASS (obj);
if (__builtin_expect
Index: java/lang/natClassLoader.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natClassLoader.cc,v
retrieving revision 1.52
diff -w -p -2 -c -r1.52 natClassLoader.cc
*** java/lang/natClassLoader.cc 11 Oct 2002 22:10:37 -0000 1.52
--- java/lang/natClassLoader.cc 2 Dec 2002 20:23:13 -0000
*************** _Jv_PrepareCompiledClass (jclass klass)
*** 327,330 ****
--- 327,332 ----
klass->notifyAll ();
+
+ _Jv_PushClass (klass);
}
*************** _Jv_InitNewClassFields (jclass ret)
*** 588,591 ****
--- 590,595 ----
ret->idt = NULL;
ret->arrayclass = NULL;
+ ret->protectionDomain = NULL;
+ ret->chain = NULL;
}
*************** _Jv_NewArrayClass (jclass element, java:
*** 732,734 ****
--- 736,766 ----
element->arrayclass = array_class;
+ }
+
+ static jclass stack_head;
+
+ // These two functions form a stack of classes. When a class is loaded
+ // it is pushed onto the stack by the class loader; this is so that
+ // StackTrace can quickly determine which classes have been loaded.
+
+ jclass
+ _Jv_PopClass (void)
+ {
+ JvSynchronize sync (&java::lang::Class::class$);
+ if (stack_head)
+ {
+ jclass tmp = stack_head;
+ stack_head = tmp->chain;
+ return tmp;
+ }
+ return NULL;
+ }
+
+ void
+ _Jv_PushClass (jclass k)
+ {
+ JvSynchronize sync (&java::lang::Class::class$);
+ jclass tmp = stack_head;
+ stack_head = k;
+ k->chain = tmp;
}
Index: java/lang/natVMThrowable.cc
===================================================================
RCS file: java/lang/natVMThrowable.cc
diff -N java/lang/natVMThrowable.cc
*** java/lang/natVMThrowable.cc 10 Nov 2002 21:07:27 -0000 1.4
--- /dev/null 1 Jan 1970 00:00:00 -0000
***************
*** 1,97 ****
- // natVMThrowable.cc - native helper methods for Throwable
-
- /* Copyright (C) 2000, 2002 Free Software Foundation, Inc
-
- This file is part of libgcj.
-
- This software is copyrighted work licensed under the terms of the
- Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
- details. */
-
- /**
- * @author Andrew Haley <aph@cygnus.com>
- * @author Mark Wielaard <mark@klomp.org>
- *
- * Native helper methods for VM specific Throwable support.
- */
-
- #include <config.h>
-
- #include <string.h>
-
- #include <jvm.h>
- #include <gcj/cni.h>
- #include <gnu/gcj/RawData.h>
- #include <java/lang/Object.h>
- #include <java-threads.h>
- #include <java/lang/Throwable.h>
- #include <java/lang/VMThrowable.h>
- #include <java/lang/Thread.h>
- #include <java-interp.h>
-
- #include <sys/types.h>
-
- #include <stdlib.h>
-
- #include <unistd.h>
-
- #ifdef HAVE_EXECINFO_H
- #include <execinfo.h>
- #endif
-
- /* FIXME: size of the stack trace is limited to 128 elements. It's
- undoubtedly sensible to limit the stack trace, but 128 is rather
- arbitrary. It may be better to configure this. */
-
- java::lang::VMThrowable *
- java::lang::VMThrowable::fillInStackTrace (java::lang::Throwable*)
- {
- if (! trace_enabled)
- return NULL;
- #if defined (HAVE_BACKTRACE)
- VMThrowable* state = new VMThrowable;
- void *p[128];
-
- // We subtract 1 from the number of elements because we don't want
- // to include the calls to fillInStackTrace in the trace.
- int n = backtrace (p, 128) - 1;
-
- _Jv_frame_info *addrs;
- if (n > 0)
- {
- #ifdef INTERPRETER
- extern void _Jv_StartOfInterpreter (void);
- extern void _Jv_EndOfInterpreter (void);
-
- java::lang::Thread *thread = java::lang::Thread::currentThread();
- _Jv_MethodChain *interp_frame
- = (thread ? reinterpret_cast<_Jv_MethodChain *> (thread->interp_frame)
- : NULL);
- #endif // INTERPRETER
-
- state->length = n;
- int len = n;
- addrs = (_Jv_frame_info *) _Jv_Malloc (n * sizeof (_Jv_frame_info));
- for (n = 0; n < len; n++)
- {
- addrs[n].addr = p[n];
- #ifdef INTERPRETER
- if (p[n] >= &_Jv_StartOfInterpreter && p[n] <= &_Jv_EndOfInterpreter)
- {
- addrs[n].interp = (void *) interp_frame->self;
- interp_frame = interp_frame->next;
- }
- else
- addrs[n].interp = 0;
- #endif // INTERPRETER
- }
- }
- else
- addrs = NULL;
-
- state->stackTraceAddrs = reinterpret_cast<gnu::gcj::RawData *> (addrs);
-
- return state;
- #endif
- return NULL;
- }
--- 0 ----