StrictMode java.lang.Throwable: обнаружен непомеченный сокет
С включенным StrictMode я только начал получать это исключение:
java.lang.Throwable: обнаружен непомеченный сокет; использовать TrafficStats.setThreadSocketTag() для отслеживания всего использования сети
4 ответа
Мое решение состояло в том, чтобы вызвать при инициализации следующее:
private static final int THREAD_ID = 10000;
TrafficStats.setThreadStatsTag(THREAD_ID);
Есть несколько способов справиться с этим исключением. Во-первых, вы должны проверить трассировку стека и убедиться, что ваш код сообщает о нарушении. Например, взгляните на следующую трассировку.
D/StrictMode: StrictMode policy violation: android.os.strictmode.UntaggedSocketViolation: Untagged socket detected; use TrafficStats.setThreadSocketTag() to track all network usage
at android.os.StrictMode.onUntaggedSocket(StrictMode.java:2124)
at com.android.server.NetworkManagementSocketTagger.tag(NetworkManagementSocketTagger.java:82)
at libcore.io.BlockGuardOs.tagSocket(BlockGuardOs.java:52)
at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:372)
at libcore.io.ForwardingOs.socket(ForwardingOs.java:217)
at libcore.io.IoBridge.socket(IoBridge.java:658)
at java.net.PlainSocketImpl.socketCreate(PlainSocketImpl.java:128)
at java.net.AbstractPlainSocketImpl.create(AbstractPlainSocketImpl.java:128)
at java.net.ServerSocket.createImpl(ServerSocket.java:306)
at java.net.ServerSocket.getImpl(ServerSocket.java:259)
at java.net.ServerSocket.bind(ServerSocket.java:377)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at com.java42.android03.binder.peer.messaging.J42PM_ServerConnection.run(J42PM_ServerConnection.java:52)
at com.java42.base.components.utility.impl.Utility_Thread$1.run(Utility_Thread.java:137)
at java.lang.Thread.run(Thread.java:919)
at com.java42.utility.base.J42Thread.run(J42Thread.java:38)
Вызов приложения с нарушением:
J42PM_ServerConnection.run(J42PM_ServerConnection.java:52)
Затем взгляните на этот код:
public void run() {
try (ServerSocket serverSocket = new ServerSocket(port)) {
this.serverSocket = serverSocket;
CallerId.identifyBasic("J42PSC0179D: listening Inbound....");
while (!Thread.currentThread().isInterrupted()) {
...
Поскольку это цикл на стороне сервера, а идентификатор потока не меняется в течение срока службы серверного процесса, вы можете исправить нарушение, добавив вызов TrafficStats.setThreadStatsTag() с использованием идентификатора текущего потока.
public void run() {
TrafficStats.setThreadStatsTag((int) Thread.currentThread().getId()); // <---
try (ServerSocket serverSocket = new ServerSocket(port)) {
this.serverSocket = serverSocket;
CallerId.identifyBasic("J42PSC0179D: listening Inbound....");
while (!Thread.currentThread().isInterrupted()) {
...
Посмотрим на еще один след:
D/StrictMode: StrictMode policy violation: android.os.strictmode.UntaggedSocketViolation: Untagged socket detected; use TrafficStats.setThreadSocketTag() to track all network usage
at android.os.StrictMode.onUntaggedSocket(StrictMode.java:2124)
at com.android.server.NetworkManagementSocketTagger.tag(NetworkManagementSocketTagger.java:82)
at libcore.io.BlockGuardOs.tagSocket(BlockGuardOs.java:52)
at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:372)
at libcore.io.ForwardingOs.socket(ForwardingOs.java:217)
at libcore.io.IoBridge.socket(IoBridge.java:658)
at java.net.PlainSocketImpl.socketCreate(PlainSocketImpl.java:128)
at java.net.AbstractPlainSocketImpl.create(AbstractPlainSocketImpl.java:128)
at java.net.Socket.createImpl(Socket.java:489)
at java.net.Socket.<init>(Socket.java:446)
at java.net.Socket.<init>(Socket.java:218)
at com.java42.android03.binder.peer.messaging.J42PM_ClientConnection.run(J42PM_ClientConnection.java:54)
at com.java42.android03.binder.peer.messaging.J42PM_Client$2.run(J42PM_Client.java:86)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Как и в первом примере, вы определяете вызов приложения, который нарушает:
J42PM_ClientConnection.run(J42PM_ClientConnection.java:54)
Затем взгляните на этот код:
InetSocketAddress socketAddress = serviceResolver.getSocketAddress();
connection = new J42PM_ClientConnection(socketAddress, responseHandler);
executorService.execute(new Runnable() {
@Override
public void run() {
connection.run();
...
Обратите внимание, что этот код использует службу исполнителя для запуска клиентского соединения. Идентификатор потока будет меняться в течение жизни процесса по мере создания и уничтожения соединений. Я не уверен, что это приведет к искажению отчетов о трафике, но я считаю, что лучше всего отслеживать использование на данном этапе, используя постоянное значение. Выберите уникальный номер. Использование номера строки файла - простой выбор.
InetSocketAddress socketAddress = serviceResolver.getSocketAddress();
connection = new J42PM_ClientConnection(socketAddress, responseHandler);
executorService.execute(new Runnable() {
@Override
public void run() {
TrafficStats.setThreadStatsTag(42); // <--
connection.run();
...
Последний комментарий: если вы не видите вызова своего кода в трассировке стека, вы мало что можете сделать, чтобы остановить нарушение. Проблема в другой библиотеке, и если вы не можете связаться с владельцем библиотеки, просто игнорируйте нарушение.
Если вы используете клиент OkHttp, создайтеInterceptor
и добавьте к нему в реализации метода перехвата следующую строку
TrafficStats.setThreadStatsTag(Thread.currentThread().id.toInt())
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(
StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork() // or .detectAll() for all detectable problems
.detectAll() // .penaltyDeath()
.penaltyLog()
.build()
)
StrictMode.setVmPolicy(
VmPolicy.Builder()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.detectAll()
.penaltyLog() // .penaltyDeath()
.build()
)
}