public static RubyClass createThreadClass(Ruby runtime) {
    // FIXME: In order for Thread to play well with the standard 'new' behavior,
    // it must provide an allocator that can create empty object instances which
    // initialize then fills with appropriate data.
    RubyClass threadClass =
        runtime.defineClass(
            "Thread", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
    runtime.setThread(threadClass);

    threadClass.index = ClassIndex.THREAD;
    threadClass.setReifiedClass(RubyThread.class);

    threadClass.defineAnnotatedMethods(RubyThread.class);

    RubyThread rubyThread = new RubyThread(runtime, threadClass);
    // TODO: need to isolate the "current" thread from class creation
    rubyThread.threadImpl = new NativeThread(rubyThread, Thread.currentThread());
    runtime.getThreadService().setMainThread(Thread.currentThread(), rubyThread);

    // set to default thread group
    runtime.getDefaultThreadGroup().addDirectly(rubyThread);

    threadClass.setMarshal(ObjectMarshal.NOT_MARSHALABLE_MARSHAL);

    if (runtime.is2_0()) {
      // set up Thread::Backtrace::Location class
      RubyClass backtrace =
          threadClass.defineClassUnder(
              "Backtrace", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
      RubyClass location =
          backtrace.defineClassUnder(
              "Location", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);

      location.defineAnnotatedMethods(Location.class);

      runtime.setLocation(location);
    }

    return threadClass;
  }