@JRubyMethod(optional = 2, compat = CompatVersion.RUBY2_0)
  public IRubyObject backtrace_locations(ThreadContext context, IRubyObject[] args) {
    ThreadContext myContext = getContext();

    if (myContext == null) return context.nil;

    Ruby runtime = context.runtime;
    Integer[] ll = RubyKernel.levelAndLengthFromArgs(runtime, args, 0);
    Integer level = ll[0], length = ll[1];

    return myContext.createCallerLocations(level, length, getNativeThread().getStackTrace());
  }
  @JRubyMethod(name = "backtrace", optional = 2, compat = CompatVersion.RUBY2_0)
  public IRubyObject backtrace20(ThreadContext context, IRubyObject[] args) {
    ThreadContext myContext = getContext();

    // context can be nil if we have not started or GC has claimed our context
    if (myContext == null) return context.nil;

    Thread nativeThread = getNativeThread();

    // nativeThread can be null if the thread has terminated and GC has claimed it
    if (nativeThread == null) return context.nil;

    Ruby runtime = context.runtime;
    Integer[] ll = RubyKernel.levelAndLengthFromArgs(runtime, args, 0);
    Integer level = ll[0], length = ll[1];

    return myContext.createCallerBacktrace(level, length, getNativeThread().getStackTrace());
  }