Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Fixes

- Prevents inclusion of `null.` prefix before default-package class names when parsing Java and JNI frames from Android ANR thread dumps ([#5979](https://github.com/getsentry/sentry-java/pull/5979))

### Dependencies

- Bump Native SDK from v0.16.2 to v0.16.3 ([#5962](https://github.com/getsentry/sentry-java/pull/5962))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ private SentryStackTrace parseStacktrace(
final SentryStackFrame frame = new SentryStackFrame();
final String packageName = javaRe.group(1);
final String className = javaRe.group(2);
final String module = String.format("%s.%s", packageName, className);
final String module = toModuleName(packageName, className);
frame.setModule(module);
frame.setFunction(javaRe.group(3));
frame.setFilename(javaRe.group(4));
Expand Down Expand Up @@ -312,7 +312,7 @@ private SentryStackTrace parseStacktrace(
final SentryStackFrame frame = new SentryStackFrame();
final String packageName = jniRe.group(1);
final String className = jniRe.group(2);
final String module = String.format("%s.%s", packageName, className);
final String module = toModuleName(packageName, className);
frame.setModule(module);
frame.setFunction(jniRe.group(3));
frame.setInApp(stackTraceFactory.isInApp(module));
Expand Down Expand Up @@ -390,6 +390,11 @@ private SentryStackTrace parseStacktrace(
return stackTrace;
}

private @NotNull String toModuleName(
final @Nullable String packageName, final @NotNull String className) {
return packageName == null || packageName.isEmpty() ? className : packageName + "." + className;
}

private void markThreads() {
for (final @NotNull SentryThread thread : threads) {
if (Boolean.TRUE.equals(thread.isMain())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package io.sentry.android.core.internal.threaddump

import io.sentry.SentryLockReason
import io.sentry.SentryOptions
import java.io.BufferedReader
import java.io.File
import java.io.StringReader
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
Expand Down Expand Up @@ -219,6 +221,56 @@ class ThreadDumpParserTest {
assertEquals("main", threads.first().name)
}

@Test
fun `uses class name as module when a Java frame has no package`() {
val lines =
Lines.readLines(
BufferedReader(
StringReader(
"""
----- pid 123 at 2023-04-04 22:06:31.064728684+0200 -----
"main" prio=5 tid=1 Runnable
| sysTid=123 nice=-10 cgrp=top-app sched=0/0 handle=0x7deceb74f8
at MainActivity.run(MainActivity.java:177)
"""
.trimIndent()
)
)
)
val parser = ThreadDumpParser(SentryOptions(), false)

parser.parse(lines)

val frame = parser.threads.single().stacktrace!!.frames!!.last()
assertEquals("MainActivity", frame.module)
}

@Test
fun `uses class name as module when a JNI frame has no package`() {
val lines =
Lines.readLines(
BufferedReader(
StringReader(
"""
----- pid 123 at 2023-04-04 22:06:31.064728684+0200 -----
"main" prio=5 tid=1 Runnable
| sysTid=123 nice=-10 cgrp=top-app sched=0/0 handle=0x7deceb74f8
at MainActivity.nativeRun(Native method)
"""
.trimIndent()
)
)
)
val parser = ThreadDumpParser(SentryOptions(), false)

parser.parse(lines)

val frame = parser.threads.single().stacktrace!!.frames!!.last()
assertEquals("MainActivity", frame.module)
assertEquals("nativeRun", frame.function)
assertEquals(true, frame.isNative)
}

@Test
fun `thread dump garbage`() {
val lines = Lines.readLines(File("src/test/resources/thread_dump_bad_data.txt"))
Expand Down
Loading