---
title: "Sửa java.lang.NullPointerException trong Kotlin và Android từ thông điệp của nó"
description: "java.lang.NullPointerException trong Kotlin đến từ !!, giá trị Java ở kiểu non-null, ép kiểu null hay lời gọi từ Java. Chúng tôi tạo nó 6 cách trên JDK 17 và nêu cách sửa cho từng thông điệp."
canonical: "https://logbrew.co/vi/errors/nullpointerexception"
last_updated: "2026-11-10"
---

# Sửa java.lang.NullPointerException trong Kotlin và Android từ thông điệp của nó

`java.lang.NullPointerException` trong Kotlin đến từ `!!`, giá trị Java ở kiểu non-null, ép kiểu `null` hay lời gọi từ Java. Chúng tôi tạo nó 6 cách trên JDK 17 và nêu cách sửa cho từng thông điệp.

Đã thử nghiệm ngày 10 tháng 11, 2026 với Kotlin 2.4.0, OpenJDK 17.0.18 và logbrew-kotlin 0.2.3

Tác giả [Furkan Erday](https://github.com/furkanerday). Furkan Erday là nhà sáng lập LogBrew. Anh xây dựng LogBrew bằng Claude Code và Codex mỗi ngày.

Canonical: https://logbrew.co/vi/errors/nullpointerexception

## Mỗi thông điệp `NullPointerException` chỉ ra điều gì

| Đoạn mã đã làm gì | `NullPointerException` | Thông điệp nêu nguyên nhân |
| --- | --- | --- |
| `order!!` trên giá trị null | Có | Không có thông điệp |
| Giá trị Java gán vào `val` non-null | Có | `getProperty(...) must not be null` |
| `null as String` | Có | `null cannot be cast to non-null type` |
| `null` từ Java vào tham số Kotlin | Có | `Parameter specified as non-null is null` |
| Gọi phương thức trên `null` trong Java | Có | `Cannot invoke "String.length()"` |
| Đọc `lateinit` trước khi gán | `UninitializedPropertyAccessException` | `lateinit property keg has not been initialized` |

6 lượt chạy trên JDK 17 với Kotlin 2.4. Cốc đầy ở cột đầu nghĩa là có `NullPointerException`, và ở cột thứ hai nghĩa là thông điệp đã nêu nguyên nhân.

## Đọc thông điệp, rồi đến frame đầu tiên

### Tìm dòng trong mã của chính bạn

Stack frame đầu tiên thuộc package của bạn nêu tên file và số dòng. Khi trace có phần `Caused by:`, đọc các frame dưới phần đó trước. Thông điệp sau đó cho bạn biết mình gặp trường hợp nào trong 5 trường hợp dưới đây.

### Không có thông điệp, do `!!` trên giá trị null

`!!` ném `NullPointerException` không kèm thông điệp, nên logger in thông điệp sau dấu hai chấm sẽ hiện `java.lang.NullPointerException: null`. Dòng trong frame đầu tiên chứa `!!`.

```bash
val order: String? = null
order!!.length
```

Kết quả

```text
java.lang.NullPointerException
	at NpeKt.main$lambda$0(Npe.kt:27)
```

### `must not be null` khi giá trị Java đi vào kiểu non-null

Phương thức Java trả về platform type, và Kotlin chỉ kiểm tra nó khi bạn gán vào biến non-null. `getProperty(...)` nêu tên lời gọi đã trả về `null`.

```bash
val beer: String = System.getProperty("taproom.beer")
```

Kết quả

```text
java.lang.NullPointerException: getProperty(...) must not be null
	at NpeKt.main$lambda$1(Npe.kt:30)
```

### `Parameter specified as non-null is null` khi Java truyền `null` vào Kotlin

Kotlin kiểm tra từng tham số non-null của hàm public khi hàm được gọi, nên `null` từ Java thất bại ngay dòng đầu của hàm. Thông điệp nêu tên hàm và tham số.

```bash
// Kotlin
fun greet(name: String): Int = name.length

// Java
NpeKt.greet(null);
```

Kết quả

```text
java.lang.NullPointerException: Parameter specified as non-null is null: method NpeKt.greet, parameter name
	at NpeKt.greet(Npe.kt)
```

### `null cannot be cast to non-null type` sau khi ép kiểu `null`

`as String` trên `null` sẽ ném lỗi. `as? String` trả về `null` thay vì ném, và trong lượt chạy của chúng tôi nó đã làm đúng vậy, không có exception.

```bash
val value: Any? = null
value as String
```

Kết quả

```text
java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String
	at NpeKt.main$lambda$2(Npe.kt:35)
```

### `Cannot invoke` từ lời gọi phương thức trên `null` trong mã Java

Từ JDK 15, Java nêu tên phương thức và biến. `<local0>` nghĩa là class được biên dịch không có `-g`, nên thiếu tên biến. Biên dịch với `javac -g` để thấy tên. Trên Android, runtime ghi `Attempt to invoke virtual method ... on a null object reference` thay vào đó.

```bash
String beer = null;
beer.length();
```

Kết quả

```text
java.lang.NullPointerException: Cannot invoke "String.length()" because "<local0>" is null
	at Caller.lengthOfNull(Caller.java:10)
```

## Sửa trong Kotlin và Android

### Thay `!!` bằng giá trị dự phòng hoặc lỗi có tên

`?:` cho giá trị mặc định hoặc thoát khỏi hàm. `requireNotNull()` kèm thông điệp thất bại ngay và nói rõ thiếu gì, nên frame đầu tiên và thông điệp đều chỉ vào nguyên nhân.

```bash
val order = orders[id] ?: return
val keg = requireNotNull(taps[id]) { "keg is not set for tap $id" }
```

Kết quả

```text
java.lang.IllegalArgumentException: keg is not set for tap 3
	at NpeKt.main$lambda$6(Npe.kt:48)
```

### Khai báo kiểu nullable ở ranh giới với Java

Gán kiểu nullable cho giá trị đến từ Java, và trình biên dịch buộc bạn xử lý `null` trước khi dùng. Đánh dấu mã Java của bạn bằng `@Nullable` và `@NonNull`, và Kotlin thấy kiểu thật thay vì platform type.

```bash
val beer: String? = System.getProperty("taproom.beer")
val name = beer ?: "house ale"
```

### Để parser JSON thất bại lúc parse, không phải sau đó

Parser dựng đối tượng bằng reflection có thể đưa `null` vào thuộc tính Kotlin non-null, và exception xuất hiện ở rất xa chỗ parse. square/moshi#143 báo cáo điều này năm 2016. Nó được đóng vào tháng 1 năm 2018 với câu trả lời là dùng adapter Kotlin, vốn từ chối trường non-null bị thiếu.

### Chỉ dùng `lateinit` cho giá trị được gán trước lần dùng đầu

Thuộc tính `lateinit` bị đọc trước khi gán ném `UninitializedPropertyAccessException`, không phải `NullPointerException`. Kiểm tra `::keg.isInitialized` trước, hoặc dùng `by lazy` khi bạn tính được giá trị.

```bash
class Taproom {
    lateinit var keg: String
}

Taproom().keg.length
```

Kết quả

```text
kotlin.UninitializedPropertyAccessException: lateinit property keg has not been initialized
	at Taproom.getKeg(Npe.kt:6)
```

### Gửi exception kèm stack của nó lên LogBrew

`captureThrowable()` trong SDK Kotlin gửi kiểu exception, các stack frame và chuỗi nguyên nhân, và LogBrew gom các lần lặp lại vào 1 vấn đề. Thông điệp không được gửi trừ khi bạn truyền `includeMessage = true`. Trong ứng dụng của bạn, truyền `HttpTransport()` cho `flush()` thay vì transport ghi lại.

```bash
import co.logbrew.sdk.LogBrewAndroid
import co.logbrew.sdk.LogBrewClient
import co.logbrew.sdk.RecordingTransport

val transport = RecordingTransport.alwaysAccept()
val client = LogBrewClient.create(apiKey = System.getenv("LOGBREW_API_KEY"), sdkName = "logbrew-kotlin", sdkVersion = "0.2.3")
try {
    val beer: String = System.getProperty("taproom.beer")
    beer.length
} catch (e: NullPointerException) {
    LogBrewAndroid.captureThrowable(client, "evt_npe_1", "2026-11-10T09:00:00Z", e)
}
println(client.flush(transport))
```

Kết quả

```text
TransportResponse(statusCode=202, attempts=1)
```

## Kết quả khi chúng tôi thử nghiệm

Chúng tôi biên dịch 1 file Kotlin và 1 file Java bằng Kotlin 2.4.0 trên OpenJDK 17.0.18 và kích hoạt exception theo 6 cách. 4 cách đến từ mã Kotlin, với `!!`, giá trị Java trong `val` non-null, `as String` trên `null`, và `null` mà Java truyền vào tham số Kotlin. Cách thứ 5 là lời gọi phương thức trên `null` trong Java. Cách thứ 6, đọc `lateinit`, hoàn toàn không phải `NullPointerException`.

Chỉ trường hợp `!!` không có thông điệp. 4 trường hợp còn lại nêu tên lời gọi, tham số, kiểu hoặc phương thức. Thông điệp Java ghi `<local0>` cho biến vì chúng tôi biên dịch không có `-g`.

`requireNotNull()` kèm thông điệp đã ném `IllegalArgumentException: keg is not set for tap 3` đúng trên dòng chúng tôi viết nó. `as? String` trả về `null` mà không có exception.

## Vì sao Kotlin vẫn ném NullPointerException

Trình biên dịch Kotlin từ chối lời gọi trên kiểu nullable, nên mã Kotlin chỉ ném `NullPointerException` ở chỗ bạn yêu cầu. Tài liệu null safety liệt kê `!!`, `throw` tường minh, `this` chưa khởi tạo và tương tác với Java là những nguyên nhân duy nhất. Ép kiểu `null` bằng `as` cũng ném, như lượt chạy của chúng tôi cho thấy.

Giá trị đến từ Java có platform type, viết là `String!` trong thông báo của trình biên dịch. Bạn có thể gán nó vào `String` hoặc `String?`. Với `String`, Kotlin kiểm tra ngay lúc gán và ném `must not be null`, đó là chỗ lượt chạy thứ 2 của chúng tôi thất bại.

JEP 358 thêm thông điệp `Cannot invoke ... because ... is null` vào JVM từ JDK 14, và JDK 15 bật nó mặc định. Runtime của Android ghi văn bản riêng. google/gson#1778 cho thấy nó từ một ứng dụng Android, dưới dạng `Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference`.

## LogBrew ghi nhận những gì

`captureThrowable()` đã gửi 1 vấn đề tên `NullPointerException` ở mức `error`, với `exception.type` là `NullPointerException`, cơ chế `android.exception` và `handled: true`. Chuỗi nguyên nhân có 1 mục cho `java.lang.NullPointerException` với 7 stack frame, mỗi frame có file, dòng, hàm và module. Frame đầu tiên là `main` trong `Npe.kt` tại dòng 58.

Thông điệp bị bỏ trống, và mục trong chuỗi ghi `messageState: "redacted"`. Với `includeMessage = true`, vấn đề mang `getProperty(...) must not be null` làm thông điệp. Với `includeStackTrace = true`, trường metadata `throwableStackTrace` giữ văn bản của trace mà không có thông điệp.

`flush()` trả lời `statusCode=202, attempts=1` qua transport ghi lại. Cùng nội dung đó đi tới LogBrew khi bạn truyền `HttpTransport()`.

## Câu hỏi thường gặp

### NullPointerException là gì?

Exception mà JVM ném khi mã dùng một tham chiếu đang giữ `null` trong lời gọi phương thức, đọc trường, chỉ số mảng hoặc unboxing. Nó kế thừa `RuntimeException`, nên không mệnh đề `throws` nào nêu tên nó.

### Vì sao Kotlin ném NullPointerException dù có null safety?

Kotlin chỉ kiểm tra nullability lúc biên dịch cho kiểu Kotlin. `!!`, `as` trên `null`, giá trị Java bạn gán vào kiểu non-null, và lời gọi từ Java truyền `null` đều ném lúc chạy. Mỗi trường hợp có thông điệp riêng, liệt kê ở trên.

### `java.lang.NullPointerException: null` nghĩa là gì?

Exception không có thông điệp. Mã in thông điệp sau dấu hai chấm sẽ ghi `null` ở đó. Trong Kotlin, `!!` ném đúng exception này, nên hãy tìm `!!` trên dòng trong frame đầu tiên.

### Parameter specified as non-null is null nghĩa là gì?

Java, hoặc reflection, đã truyền `null` vào hàm Kotlin có tham số non-null. Thông điệp nêu tên hàm và tham số. Đặt tham số thành nullable, hoặc chặn `null` từ phía bên gọi.

### Làm sao sửa NullPointerException trên Android?

Đọc frame dưới `Caused by:` thuộc package của bạn, rồi đối chiếu thông điệp với các trường hợp ở trên. Trên Android, runtime ghi `Attempt to invoke virtual method ... on a null object reference`, và phương thức nó nêu tên là lời gọi trên `null`.

### NullPointerException có phải checked exception không?

Không. Nó kế thừa `RuntimeException`, nên trình biên dịch không buộc bạn bắt nó. Sửa nguyên nhân thay vì bắt nó, vì `null` lọt tới lời gọi phương thức là bug ở đoạn mã trước đó.

## Xem mọi NullPointerException kèm stack của nó

SDK Kotlin của LogBrew gửi mỗi exception kèm kiểu, các stack frame và chuỗi nguyên nhân, và LogBrew gom các lần lặp lại vào 1 vấn đề. Bắt đầu với gói miễn phí rộng rãi, không cần thẻ.

[Bắt đầu miễn phí](https://logbrew.co/vi)

## Nguồn

- [Kotlin docs, Null safety](https://kotlinlang.org/docs/null-safety.html)
- [Kotlin docs, Null-safety and platform types](https://kotlinlang.org/docs/java-interop.html#null-safety-and-platform-types)
- [JEP 358, Helpful NullPointerExceptions](https://openjdk.org/jeps/358)
- [square/moshi#143](https://github.com/square/moshi/issues/143)
- [google/gson#1778](https://github.com/google/gson/issues/1778)

## Thêm cách sửa lỗi

- [Sửa lỗi Script error khiến thông điệp, file và số dòng bị ẩn](https://logbrew.co/vi/errors/script-error)
- [Sửa lỗi Failed to fetch và phân biệt 3 nguyên nhân](https://logbrew.co/vi/errors/failed-to-fetch)
- [Những lỗi chúng tôi đã tái hiện, và cách sửa từng lỗi](https://logbrew.co/vi/errors)
