Итак, я понял это.
Небольшая заметка, и я, вероятно, должен был упомянуть об этом в своем вопросе: рассматриваемая трассировка стека не была результатом сбоя / исключения, а скорее была напечатана в покажите, где был поток до того, как сторожевой таймер убил его, потому что он не отвечал.
- Если это не тупик, то он был вызван, по крайней мере, конфликтом длинных потоков
- Что за трассировка стека выглядит так, когда поток ожидает вызова метода
synchronized
, когда другой поток выполняет другой метод synchronized
, отличается от ART и JVM!
В ART кадр верхнего стека будет показан как в методе без номера строки, но в JVM он будет показан как первая строка в методе с номером строки.
Вот «полная, минимальная, воспроизводимая» пример для Android:
public class MainActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
launchThread("TH1");
sleep(100);
launchThread("TH2");
sleep(20);
dumpThreadTraces();
}
void launchThread(String name)
{
Thread thread = new Thread(new Runnable()
{
@Override
public void run()
{
doThings();
}
});
thread.setName(name);
thread.start();
}
synchronized void doThings()
{
sleep(1000);
}
void dumpThreadTraces()
{
Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
Set<Thread> threads = traces.keySet();
for(Thread th : threads)
{
if(th.getName().startsWith("TH"))
{
logStackTrace(th, traces.get(th));
}
}
}
void logStackTrace(Thread thread, StackTraceElement[] stackTrace)
{
System.out.printf("thread id=%d name=\"%s\"\n", thread.getId(), thread.getName());
logStackFrames(stackTrace);
}
void logStackFrames(StackTraceElement[] stackTrace)
{
for (StackTraceElement frame : stackTrace)
{
System.out.printf(" at %s\n", frame.toString());
}
}
void sleep(int millis)
{
try
{
Thread.sleep(millis);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
При запуске в logcat будет напечатано следующее:
I/System.out: thread id=2051 name="TH1"
I/System.out: at java.lang.Thread.sleep(Native Method)
I/System.out: at java.lang.Thread.sleep(Thread.java:371)
I/System.out: at java.lang.Thread.sleep(Thread.java:313)
I/System.out: at com.domain.helloworld.MainActivity.sleep(MainActivity.java:94)
I/System.out: at com.domain.helloworld.MainActivity.doThings(MainActivity.java:58)
I/System.out: at com.domain.helloworld.MainActivity$1.run(MainActivity.java:48)
I/System.out: at java.lang.Thread.run(Thread.java:761)
I/System.out: thread id=2052 name="TH2"
I/System.out: at com.domain.helloworld.MainActivity.doThings(MainActivity.java)
I/System.out: at com.domain.helloworld.MainActivity$1.run(MainActivity.java:48)
I/System.out: at java.lang.Thread.run(Thread.java:761)
Обратите внимание, как для потока 2 - номер строки для элемента трассировки верхнего стека нет т напечатан!
at com.domain.helloworld.MainActivity.doThings(MainActivity.java)