Группы процессов
Все процессы принадлежат к группам процессов. Это может быть группа процессов по умолчанию, или группа явно указанная при создании процесса. Во время создания процесс привязан к группе и не может сменить ее на другую группу. Каждое приложение имеет, по крайне мере, один процесс, который принадлежит системной группе процессов. При создании нескольких процессов без указания группы, они также будут принадлежать системной группе. Одна группа процессов также может принадлежать другой группе процессов.
Группа процессов, к которой принадлежит только что созданная (не понятно, созданная(ый) кто - группа или процесс - прим. перев.), должна быть указана в конструкторе. Если создается группа процессов без указания группы, к которой она должна принадлежать, то она помещается в системную группу. Таким образом, все процессы приложения в конечном счете имеют системную группу в качестве предка.
Причина существования групп процессов трудно понять из литературы, которые обычно не четко описывают данную область. Чаще всего цитируется "по причине защиты". Соглачно Arnold & Gosling,[71] "Threads within a thread group can modify the other threads in the group, including any farther down the hierarchy. A thread cannot modify threads outside of its own group or contained groups." (Процессы в группе могут изменять другие процессы этой группы, включая все последующие согласно иерархии. Процесс не может изменять процессы не входящие в его группу или группы в его группе). Довольно трудно понять, что означает "изменять" в приведенной цитате. Следующий пример показывает процесс в подгруппе "leaf", который изменяет приоритеты всех процессов в его дереве группы процессов, а также и сам метод, вызываемый для всех процессов в дереве.
//: c14:TestAccess.java
// How threads can access other threads
// in a parent thread group.
public class TestAccess { public static void main(String[] args) { ThreadGroup x = new ThreadGroup("x"), y = new ThreadGroup(x, "y"), z = new ThreadGroup(y, "z"); Thread one = new TestThread1(x, "one"), two = new TestThread2(z, "two"); } }
class TestThread1 extends Thread { private int i; TestThread1(ThreadGroup g, String name) { super(g, name); } void f() { i++; // modify this thread
System.out.println(getName() + " f()"); } }
class TestThread2 extends TestThread1 { TestThread2(ThreadGroup g, String name) { super(g, name); start(); } public void run() { ThreadGroup g = getThreadGroup().getParent().getParent(); g.list(); Thread[] gAll = new Thread[g.activeCount()]; g.enumerate(gAll); for(int i = 0; i < gAll.length; i++) { gAll[i].setPriority(Thread.MIN_PRIORITY); ((TestThread1)gAll[i]).f(); } g.list(); } } ///:~
В main() создается несколько ThreadGroup накладываясь друг на друга: х не имеет аргументов, за исключением своего имени (String) , так что он автоматически помещается в "системную" группу процессов, до тех пор пока y меньше х и z меньше у. Обратите внимание, что инициализация происходит в той же последовательности как написано, так что этот код правилен.
Два процесса создаются и помещаются в разные группы процессов. TestThread1 не имеет метода run(), но имеет метод f(), который изменяет процесс и выводит сообщение, чтобы вы знали, что он был вызван. TestThread2 является подклассом TestThread1 и его run() довольно сложен. В начале он определяет группу процессов текущего процесса, затем перемещается по дереву наследования на два уровня используя getParent(). (Это задумано поскольку я специально поместил объект TestThread2 на два уровня ниже по иерархии.) В этом месте создается массив ссылок на Thread используя метод activeCount(), чтобы знать, сколько процессов в данной группе и во всех подгруппах. Метод enumerate() помещает ссылки на все процессы в массив gAll, а затем я просто перемещаюсь по всему массиву вызывая метод f() для каждого процесса, заодно меняя приоритет. Таким образом, процесс в группе "leaf" изменяет процессы в группах родителя.
Отладочный метод list() выводит всю информацию о группе процессов на стандартный вывод, что полезно при изучении поведения процессов. Ниже приведена работа программы:
java.lang.ThreadGroup[name=x,maxpri=10] Thread[one,5,x] java.lang.ThreadGroup[name=y,maxpri=10] java.lang.ThreadGroup[name=z,maxpri=10] Thread[two,5,z] one f() two f() java.lang.ThreadGroup[name=x,maxpri=10] Thread[one,1,x] java.lang.ThreadGroup[name=y,maxpri=10] java.lang.ThreadGroup[name=z,maxpri=10] Thread[two,1,z]
Метод list() не только выводит имя класса для ThreadGroup или Thread, но также и имя группы и ее максимальный приоритет. Для процессов имя процесса выводится после приоритета и имени группы, к которой он принадлежит. Обратите внимание, что list() вставляет отступы для процессов и групп процессов, чтобы показать, что они являются дочерни по отношении к группе без отступа.
Можно видеть, что f() вызывается методом run() из TestThread2, так что совершенно очевидно, что все процессы в группе уязвимы (vulnerable). Однако доступ возможен только к процессам являющимися подветвью вашей системной группы процессов и, вероятно, это и подразумевают под "безопастностью". Доступ к чужим системным группам не возможен.