Question about a comment in _Jv_StackTrace::UnwindTraceFn

Andrew Haley aph@redhat.com
Thu May 21 17:15:00 GMT 2009


Dave Korn wrote:
>     Hi java team,
> 
>   It suggests to me here that there should be an entry on the interpreter
> stack corresponding to every entry though the interpreter's main function on
> the CPU's native stack:
> 
> 122       // If we see the interpreter's main function, "pop" an entry off the
> 123       // interpreter stack and use that instead, so that the trace goes
> through
> 124       // the java code and not the interpreter itself. This assumes a 1:1
> 125       // correspondance between call frames in the interpreted stack and
> occurances
> 126       // of _Jv_InterpMethod::run() on the native stack.
> 
>   I wonder if this assumption is still correct?  Or maybe it's a side-effect
> of having configured with --enable-libgcj-debug?
> 
> 127     #ifdef INTERPRETER
> 128       void *interp_run = NULL;
> 129
> 130       if (::gnu::classpath::jdwp::Jdwp::isDebugging)
> (gdb)
> 131             interp_run = (void *) &_Jv_InterpMethod::run_debug;
> 132       else
> 133         interp_run = (void *) &_Jv_InterpMethod::run;
> 134
> 135       if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> 136         {
> 137           state->frames[pos].type = frame_interpreter;
> 138           _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 139           state->frames[pos].interp.meth
> 140             = static_cast<_Jv_InterpMethod *> (frame->self);
> 
> ... because I'm getting a NULL pointer here.  I saw that
> gnu::classpath::jdwp::Jdwp::isDebugging is zero, so we're looking for the
> plain run method, not run_debug.
> 
> (gdb) print ((_Jv_UnwindState *) state_ptr)[0]
> $6 = {length = 100, pos = 23, frames = 0x22bba0, interp_frame = 0x0,
>   trace_function = 0, trace_data = 0x0}
> (gdb)
> 
>   There's no interp_frame entries.  Looking at the stack trace:
> 
> (gdb) bt
> #0  _Jv_StackTrace::UnwindTraceFn (context=0x22bafc, state_ptr=0x22c388)
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:140
> #1  0x67f0660d in _Unwind_Backtrace (
>     trace=0x5f0940 <_Jv_StackTrace::UnwindTraceFn(_Unwind_Context*, void*)>,
>     trace_argument=0x22c388)
>     at /usr/src/gcc/gcc4-4.3.2-2/src/gcc-4.3.2/libgcc/../gcc/unwind.inc:302
> #2  0x005f0d2f in _Jv_StackTrace::GetStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/stacktrace.cc:192
> #3  0x005c5354 in java::lang::VMThrowable::fillInStackTrace ()
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMThrowable.cc:33
> #4  0x00406400 in java.lang.Throwable.fillInStackTrace()java.lang.Throwable (
>     this=0x29e8468)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:500
> #5  0x0041c84d in java.lang.Throwable.Throwable(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Throwable.java:161
> #6  0x0041faf7 in java.lang.Exception.Exception(java.lang.String) (
>     this=0x29e8468, s=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/lang/Exception.java:78
> #7  0x005468d7 in java.io.IOException.IOException(java.lang.String) (
>     this=0x29e8468, message=0x29ef5b0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/io/IOException.java:72
> #8  0x0073c154 in gnu::gcj::Core::create (name=0x29e8498)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/natCore.cc:118
> #9  0x005f1f05 in gnu.java.net.protocol.core.Connection.connect()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:5
> 0
> #10 0x005f208f in gnu.java.net.protocol.core.Connection.getHeaders()void (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:1
> 54
> #11 0x005f22c5 in gnu.java.net.protocol.core.Connection.getHeaderField(java.lang
> .String)java.lang.String (this=0x29ef5e8, name=0x28f8070)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/net/protocol/core/Connection.java:6
> 9
> #12 0x0051cdae in java.net.URLConnection.getHeaderFieldInt(java.lang.String, int
> )int (this=0x29ef5e8, name=0x28f8070, defaultValue=-1)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:426
> #13 0x0051b8a3 in java.net.URLConnection.getContentLength()int (
>     this=0x29ef5e8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLConnection.java:302
> #14 0x0071db1b in gnu.java.net.loader.RemoteURLLoader.getResource(java.lang.Stri
> ng)gnu.java.net.loader.Resource (this=0x29d1dc0, name=0x29e84c8)
>     at /gnu/gcc/gcc-patched/libjava/classpath/gnu/java/net/loader/RemoteURLLoade
> r.java:79
> #15 0x00532d7c in java.net.URLClassLoader.findClass(java.lang.String)java.lang.C
> lass (this=0x29ab370, className=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/classpath/java/net/URLClassLoader.java:528
> #16 0x004311cc in gnu.gcj.runtime.BootClassLoader.bootLoadClass(java.lang.String
> )java.lang.Class (this=0x29ab370, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/gnu/gcj/runtime/BootClassLoader.java:68
> #17 0x005c7ff5 in java::lang::VMClassLoader::loadClass (name=0x29f8ec0,
>     resolve=0 '\0')
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natVMClassLoader.cc:223
> #18 0x0042022b in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x29120f0, name=0x29f8ec0, resolve=false)
> ---Type <return> to continue, or q <return> to quit---
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:439
> #19 0x0042020d in java.lang.ClassLoader.loadClass(java.lang.String, boolean)java
> .lang.Class (this=0x2912050, name=0x29f8ec0, resolve=false)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:445
> #20 0x00407701 in java.lang.ClassLoader.loadClass(java.lang.String)java.lang.Cla
> ss (this=0x2912050, name=0x29f8ec0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/ClassLoader.java:387
> #21 0x004496a2 in _Jv_FindClass (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:512
> #22 0x00449737 in _Jv_FindClassNoException (name=0x29e7930, loader=0x2912050)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClassLoader.cc:476
> #23 0x0043e86b in _Jv_Linker::resolve_pool_entry (klass=0x294d4c0, index=97,
>     lazy=false) at /gnu/gcc/gcc-patched/libjava/link.cc:440
> #24 0x0044e695 in _Jv_InterpMethod::run (retp=0x22cb40, args=0x22cb60,
>     meth=0x292e870) at /gnu/gcc/gcc-patched/libjava/interpret-run.cc:2385
> #25 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #26 0x0044836c in java::lang::Class::initializeClass (this=0x294d4c0)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natClass.cc:780
> #27 0x00451d3b in _Jv_InterpMethod::run_class (ret=0x22cbc0, args=0x22cbe0,
>     __this=0x2918c00) at /gnu/gcc/gcc-patched/libjava/java/lang/Class.h:742
> #28 0x00780c45 in ffi_closure_raw_SYSV ()
>     at /gnu/gcc/gcc-patched/libffi/src/x86/win32.S:338
> #29 0x0061c684 in gnu::java::lang::MainThread::call_main (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/natMainThread.cc:54
> #30 0x0043946a in gnu.java.lang.MainThread.run()void (this=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/gnu/java/lang/MainThread.java:106
> #31 0x004687b4 in _Jv_ThreadRun (thread=0x29af540)
>     at /gnu/gcc/gcc-patched/libjava/java/lang/natThread.cc:335
> #32 0x00404b7d in _Jv_RunMain (vm_args=0x22ccb0, klass=0x0,
>     name=0x22cd4c "/gnu/gcc/gcc-patched/libjava/testsuite/libjava.jar/TestClosur
> eGC.jar", argc=1, argv=0x28b9d48, is_jar=true)
>     at /gnu/gcc/gcc-patched/libjava/prims.cc:1789
> #33 0x00401392 in main (argc=3, argv=0x28b9d40)
>     at /gnu/gcc/gcc-patched/libjava/gij.cc:333
> (gdb)
> 
> ... there is a single call to _Jv_InterpMethod::run, at frame #24, coming from
> a call to ffi_closure_raw_SYSV.
> 
>   I've worked around this before by just avoiding the situation with
> 
> Index: libjava/stacktrace.cc
> ===================================================================
> --- libjava/stacktrace.cc	(revision 147638)
> +++ libjava/stacktrace.cc	(working copy)
> @@ -132,7 +132,8 @@
>    else
>      interp_run = (void *) &_Jv_InterpMethod::run;
>    	
> -  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run))
> +  if (func_addr == UNWRAP_FUNCTION_DESCRIPTOR (interp_run)
> +      && state->interp_frame)
>      {
>        state->frames[pos].type = frame_interpreter;
>        _Jv_Frame *frame = static_cast<_Jv_Frame *> (state->interp_frame);
> 
> ... but is that the right thing to do?  Where should state->interp_frame have
> been set up?  It appears to fix testsuite failures, but I don't know for sure
> if they're doing everything right internally.  I'll run it through a test
> cycle if just avoiding the problem in this way is indeed correct, but a
> pointer or two could speed me on the way or save me barking up any wrong trees.

You need to put a breakpoint at the constructor of _Jv_InterpFrame.  It creates
a node and pushes it into the linked list starting at thr->interp_frame:

  _Jv_InterpFrame (void *meth, java::lang::Thread *thr, jclass proxyCls = NULL,
                   pc_t *pc = NULL,
		   _Jv_FrameType frame_type = frame_interpreter)
  : _Jv_Frame (reinterpret_cast<_Jv_MethodBase *> (meth), thr,
	             frame_type)
  {
    next_interp = (_Jv_InterpFrame *) thr->interp_frame;
    proxyClass = proxyCls;
    thr->interp_frame = (gnu::gcj::RawData *) this;
    obj_ptr = NULL;
    pc_ptr = pc;
  }

This constructor is called from interpret-run.cc:27.

Andrew.



More information about the Java mailing list