JDK-8256644 : Terminally deprecate ThreadGroup stop, destroy, isDestroyed, setDaemon and isDaemon
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.lang
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 16
  • Submitted: 2020-11-19
  • Updated: 2020-11-24
  • Resolved: 2020-11-24
Related Reports
CSR :  
Description
Summary
-------

Terminally deprecate the following methods defined by `java.lang.ThreadGroup`

- `stop()`
- `destroy()`
- `isDestroyed()`
- `setDaemon(boolean)`
- `boolean isDaemon()`

so they can be removed in a future release.


Problem
-------

`java.lang.ThreadGroup` is a legacy API from JDK 1.0. It is mostly irrelevant for modern applications and libraries.

The `stop` method is inherently unsafe and has been deprecated since Java SE 1.2. There is little evidence of real use (a survey of 100k artifacts in Maven Central found only 3 usages).

The `destroy`, `isDestroyed`, `setDaemon` and `isDaemon` methods support the mechanism to explicitly or automatically destroy an empty thread group. This mechanism is flawed and inhibits efforts to change ThreadGroup to not keep references to the Threads in the group.

To avoid a memory leak, users need to explicitly destroy a thread group when it is empty and no longer needed, or set its daemon status so that the group is automatically destroyed when the last thread in the group terminates. There will often not be a reliable point to destroy a thread group and/or set the daemon status:

- ThreadGroup::destroy is not an atomic operation. It can fail with IllegalThreadStateException after destroying some, but not all, subgroups.

- Threads can be created, but not started, before their thread group is destroyed. This can lead to Thread::start failing with an undocumented IllegalThreadStateException.

- If setDaemon(true) is called after starting threads in the group then it races with the termination of the last thread in the group. If the last thread terminates before setDaemon is called then the group will not be destroyed.

- If setDaemon(true) is called before starting threads in the group then it also races with thread termination when there is more than one thread in the group. Thread termination may destroy the group before the remaining threads have been created or started.

Our survey of 100k artifacts in Maven Central found 57 usages of `destroy`, 71 usages of `isDestroyed`, 153 usages of `setDaemon` and 12 usages of `isDaemon`, many of the usages are in older/legacy libraries.

JDK-8252885 is a draft JEP that provides more context for the deprecations proposed here. The JEP amounts to pushing ThreadGroup "out of the way with minimum disruption" in advance of Project Loom. The "replacement" for destroying a thread group in the draft JEP is to allow thread groups be GC'ed when there are no live threads in the group and there is nothing else keeping the thread group alive.


Solution
--------

Terminally deprecate the 5 methods so they can be removed in a future release.  We will examine `Thread::stop` in a separate issue.


Specification
-------------

stop()
```
    @Deprecated(since="1.2", forRemoval=true)
    public final void stop()
```

destroy()
```
     * @deprecated The API and mechanism for destroying a ThreadGroup is inherently
     *             flawed. The ability to explicitly or automatically destroy a
     *             thread group will be removed in a future release.

    @Deprecated(since="16", forRemoval=true)
    public final void destroy()
```

isDestroyed
```     
     * @deprecated The API and mechanism for destroying a ThreadGroup is inherently
     *             flawed. The ability to explicitly or automatically destroy a
     *             thread group will be removed in a future release.

    @Deprecated(since="16", forRemoval=true)
    public boolean isDestroyed()
```


setDaemon
```
     * @deprecated The API and mechanism for destroying a ThreadGroup is inherently
     *             flawed. The ability to explicitly or automatically destroy a
     *             thread group, and the concept of daemon thread group, will be
     *             removed in a future release.

    @Deprecated(since="16", forRemoval=true)
    public final void setDaemon(boolean daemon)
```

isDaemon
```
     * @deprecated The API and mechanism for destroying a ThreadGroup is inherently
     *             flawed. The ability to explicitly or automatically destroy a
     *             thread group, and the concept of daemon thread group, will be
     *             removed in a future release.

    @Deprecated(since="16", forRemoval=true)
    public final boolean isDaemon()
```

Comments
Moving to Approved.
24-11-2020