Class SubjectInheritingThread

java.lang.Object
java.lang.Thread
org.apache.hadoop.util.concurrent.SubjectInheritingThread
All Implemented Interfaces:
Runnable
Direct Known Subclasses:
DelegationTokenRenewer, GcTimeMonitor

public class SubjectInheritingThread extends Thread
Helper class to restore Subject propagation behavior of threads after the JEP411/JEP486 changes.

Java propagates the current Subject to any new Threads in all version up to Java 21. In Java 22-23 the Subject is only propagated if the SecurityManager is enabled, while in Java 24+ it is never propagated.

Hadoop security heavily relies on the original behavior, as Subject is at the core of JAAS. This class wraps thread. It overrides start() and saves the Subject of the current thread, and wraps the payload in a Subject.doAs()/callAs() call to restore it in the newly created Thread.

When specifying a Runnable, this class is used in exactly the same way as Thread.

run() cannot be directly overridden, as that would also override the subject restoration logic. SubjectInheritingThread provides a work() method instead, which is wrapped and invoked by its own final run() method.

  • Constructor Details

    • SubjectInheritingThread

      public SubjectInheritingThread()
      Behaves similarly to Thread() constructor, but the code to run must be specified by overriding the work() instead of the {link #run()} method.
    • SubjectInheritingThread

      public SubjectInheritingThread(Runnable target)
      Behaves similarly to Thread(Runnable) constructor.
      Parameters:
      target - the object whose run method is invoked when this thread is started. If null, this classes run method does nothing.
    • SubjectInheritingThread

      public SubjectInheritingThread(ThreadGroup group, Runnable target)
      Behaves similarly to Thread(ThreadGroup, Runnable) constructor.
      Parameters:
      group - the thread group. If null and there is a security manager, the group is determined by SecurityManager.getThreadGroup(). If there is not a security manager or SecurityManager.getThreadGroup() returns null, the group is set to the current thread's thread group.
      target - the object whose run method is invoked when this thread is started. If null, this thread's run method is invoked.
      Throws:
      SecurityException - if the current thread cannot create a thread in the specified thread group
    • SubjectInheritingThread

      public SubjectInheritingThread(Runnable target, String name)
      Behaves similarly to Thread(Runnable, String) constructor.
      Parameters:
      target - the object whose run method is invoked when this thread is started. If null, this thread's run method is invoked.
      name - the name of the new thread
      Throws:
      SecurityException - if the current thread cannot create a thread in the specified thread group
    • SubjectInheritingThread

      public SubjectInheritingThread(String name)
      Behaves similarly to Thread(String) constructor.
      Parameters:
      name - the name of the new thread
    • SubjectInheritingThread

      public SubjectInheritingThread(ThreadGroup group, String name)
      Behaves similarly to Thread(ThreadGroup, String) constructor.
      Parameters:
      group - the thread group. If null and there is a security manager, the group is determined by SecurityManager.getThreadGroup(). If there is not a security manager or SecurityManager.getThreadGroup() returns null, the group is set to the current thread's thread group.
      name - the name of the new thread
    • SubjectInheritingThread

      public SubjectInheritingThread(ThreadGroup group, Runnable target, String name)
      Behaves similarly to Thread(ThreadGroup, Runnable, String) constructor.
      Parameters:
      group - the thread group. If null and there is a security manager, the group is determined by SecurityManager.getThreadGroup(). If there is not a security manager or SecurityManager.getThreadGroup() returns null, the group is set to the current thread's thread group.
      target - the object whose run method is invoked when this thread is started. If null, this thread's run method is invoked.
      name - the name of the new thread
      Throws:
      SecurityException - if the current thread cannot create a thread in the specified thread group or cannot override the context class loader methods.
  • Method Details

    • start

      public final void start()
      Behaves similarly to pre-Java 22 Thread.start(). It saves the current Subject before starting the new thread, which is then used as the Subject for the Runnable or the overridden work() method.
      Overrides:
      start in class Thread
    • work

      public void work()
      This is the equivalent of Thread.run(). Override this instead of run() Subject will be propagated like in pre-Java 22 Thread.
    • run

      public final void run()
      This cannot be overridden in this class. Override the work() method instead which behaves like pre-Java 22 Thread.run()
      Specified by:
      run in interface Runnable
      Overrides:
      run in class Thread