NullAway adalah alat untuk membantu menghilangkan NullPointerException
(NPE) dalam kode Java Anda. Untuk menggunakan NullAway, pertama-tama tambahkan anotasi @Nullable
dalam kode Anda di mana pun bidang, parameter metode, atau nilai kembalian mungkin null
. Dengan adanya anotasi ini, NullAway melakukan serangkaian pemeriksaan lokal berbasis tipe untuk memastikan bahwa setiap penunjuk yang didereferensi dalam kode Anda tidak boleh null
. NullAway mirip dengan pemeriksaan nullability berbasis tipe dalam bahasa Kotlin dan Swift, serta Checker Framework dan Eradicate null checker untuk Java.
NullAway cepat . Itu dibuat sebagai plugin untuk Rawan Kesalahan dan dapat berjalan di setiap build kode Anda. Dalam pengukuran kami, overhead waktu build untuk menjalankan NullAway biasanya kurang dari 10%. NullAway juga praktis : tidak mencegah semua kemungkinan NPE dalam kode Anda, namun menangkap sebagian besar NPE yang telah kami amati dalam produksi sambil menerapkan beban anotasi yang masuk akal, memberikan "keuntungan" yang luar biasa.
NullAway mengharuskan Anda membuat kode dengan Rawan Kesalahan, versi 2.14.0 atau lebih tinggi. Lihat dokumentasi Rawan Kesalahan untuk petunjuk memulai Rawan Kesalahan dan integrasi dengan sistem build Anda. Petunjuk di bawah ini mengasumsikan Anda menggunakan Gradle; lihat dokumen untuk diskusi tentang sistem build lainnya.
Untuk mengintegrasikan NullAway ke dalam proyek Java non-Android Anda, tambahkan kode berikut ke file build.gradle
Anda:
plugins {
// we assume you are already using the Java plugin
id " net.ltgt.errorprone " version " <plugin version> "
}
dependencies {
errorprone " com.uber.nullaway:nullaway:<NullAway version> "
// Some source of nullability annotations; JSpecify recommended,
// but others supported as well.
api " org.jspecify:jspecify:1.0.0 "
errorprone " com.google.errorprone:error_prone_core:<Error Prone version> "
}
import net.ltgt.gradle.errorprone.CheckSeverity
tasks . withType( JavaCompile ) {
options . errorprone {
check( " NullAway " , CheckSeverity . ERROR )
option( " NullAway:AnnotatedPackages " , " com.uber " )
}
// Include to disable NullAway on test code
if (name . toLowerCase() . contains( " test " )) {
options . errorprone {
disable( " NullAway " )
}
}
}
Mari kita telusuri skrip ini langkah demi langkah. Bagian plugins
menggunakan plugin Gradle Error Prone untuk integrasi Error Prone.
Dalam dependencies
, baris errorprone
pertama memuat NullAway, dan baris api
memuat pustaka JSpecify yang menyediakan anotasi nullability yang sesuai, misalnya org.jspecify.annotations.Nullable
. NullAway mengizinkan penggunaan anotasi @Nullable
apa pun, jadi, misalnya, @Nullable
dari Library anotasi AndroidX atau anotasi JetBrains juga boleh digunakan. Baris errorprone
kedua mengatur versi Rawan Kesalahan yang digunakan.
Terakhir, di bagian tasks.withType(JavaCompile)
, kami meneruskan beberapa opsi konfigurasi ke NullAway. check("NullAway", CheckSeverity.ERROR)
menyetel masalah NullAway ke tingkat kesalahan (setara dengan argumen Rawan Kesalahan standar -Xep:NullAway:ERROR
); secara default NullAway mengeluarkan peringatan. Kemudian, option("NullAway:AnnotatedPackages", "com.uber")
(setara dengan -XepOpt:NullAway:AnnotatedPackages=com.uber
argumen Rawan Kesalahan standar) memberi tahu NullAway bahwa kode sumber dalam paket di bawah namespace com.uber
seharusnya memeriksa dereferensi nol dan penggunaan anotasi @Nullable
yang tepat, dan bahwa file kelas dalam paket ini harus diasumsikan memiliki penggunaan yang benar @Nullable
(lihat dokumen untuk detail lebih lanjut). NullAway memerlukan setidaknya argumen konfigurasi AnnotatedPackages
untuk dijalankan, untuk membedakan antara kode yang dianotasi dan yang tidak dianotasi. Lihat dokumen konfigurasi untuk opsi konfigurasi berguna lainnya. Untuk konfigurasi opsi NullAway yang lebih sederhana, gunakan plugin Gradle NullAway. Terakhir, kami menunjukkan cara menonaktifkan NullAway pada kode pengujian, jika diinginkan.
Kami merekomendasikan untuk mengatasi semua masalah yang dilaporkan Rawan Kesalahan, khususnya yang dilaporkan sebagai kesalahan (bukan peringatan). Namun, jika Anda ingin mencoba NullAway tanpa menjalankan pemeriksaan Rawan Kesalahan lainnya, Anda dapat menggunakan options.errorprone.disableAllChecks
(setara dengan meneruskan "-XepDisableAllChecks"
ke kompiler, sebelum argumen khusus NullAway).
Plugin Rawle Error Prone versi 3.0.0 dan yang lebih baru tidak lagi mendukung Android. Jadi jika Anda menggunakan versi terbaru plugin ini, Anda perlu menambahkan beberapa konfigurasi lebih lanjut untuk menjalankan Rawan Kesalahan dan NullAway. File contoh build.gradle
aplikasi kami menunjukkan satu cara untuk melakukan hal ini, namun proyek Android Anda mungkin memerlukan penyesuaian. Sebagai alternatif, Plugin Rawle Error Prone versi 2.x masih mendukung Android dan mungkin masih berfungsi dengan proyek Anda.
Selain itu, dibandingkan dengan konfigurasi Java, ketergantungan JSpecify dapat dihilangkan; Anda dapat menggunakan anotasi androidx.annotation.Nullable
dari pustaka anotasi AndroidX.
Beberapa pemroses anotasi seperti Dagger dan AutoValue menghasilkan kode ke dalam namespace paket yang sama dengan kode Anda sendiri. Hal ini dapat menyebabkan masalah saat mengatur NullAway ke tingkat ERROR
seperti yang disarankan di atas, karena kesalahan dalam kode yang dihasilkan ini akan memblokir pembangunan. Saat ini solusi terbaik untuk masalah ini adalah menonaktifkan sepenuhnya Rawan Kesalahan pada kode yang dihasilkan, menggunakan opsi -XepExcludedPaths
yang ditambahkan di Rawan Kesalahan 2.1.3 (didokumentasikan di sini, gunakan options.errorprone.excludedPaths=
di Gradle). Untuk menggunakannya, cari tahu direktori mana yang berisi kode yang dihasilkan, dan tambahkan direktori tersebut ke regex jalur yang dikecualikan.
Catatan untuk pengguna Dagger : Versi Dagger yang lebih tua dari 2.12 dapat memiliki interaksi yang buruk dengan NullAway; lihat di sini. Harap perbarui ke Dagger 2.12 untuk memperbaiki masalah.
Tidak seperti pemroses anotasi lain di atas, Lombok memodifikasi AST dalam memori dari kode yang diprosesnya, yang merupakan sumber dari banyak ketidakcocokan dengan Rawan Kesalahan dan, akibatnya, NullAway.
Kami tidak terlalu menyarankan penggunaan NullAway dengan Lombok. Namun, NullAway mengkodekan beberapa pengetahuan tentang anotasi umum Lombok dan kami mencoba untuk kompatibilitas upaya terbaik. Secara khusus, penggunaan umum seperti kelas @lombok.Builder
dan @Data
harus didukung.
Agar NullAway berhasil mendeteksi kode yang dihasilkan Lombok dalam Java AST dalam memori, opsi konfigurasi berikut harus diteruskan ke Lombok sebagai bagian dari file lombok.config
yang berlaku:
lombok.addLombokGeneratedAnnotation = true
Hal ini menyebabkan Lombok menambahkan @lombok.Generated
ke metode/kelas yang dihasilkannya. NullAway akan mengabaikan (yaitu tidak memeriksa) implementasi kode yang dihasilkan ini, dan memperlakukannya sebagai kode yang tidak diberi catatan.
Mari kita lihat cara kerja NullAway dengan contoh kode sederhana:
static void log ( Object x ) {
System . out . println ( x . toString ());
}
static void foo () {
log ( null );
}
Kode ini bermasalah: ketika foo()
dipanggil, panggilan berikutnya ke log()
akan gagal dengan NPE. Anda dapat melihat kesalahan ini di aplikasi contoh NullAway dengan menjalankan:
cp sample/src/main/java/com/uber/mylib/MyClass.java.buggy sample/src/main/java/com/uber/mylib/MyClass.java
./gradlew build
Secara default, NullAway mengasumsikan setiap parameter metode, nilai kembalian, dan bidang adalah non-null , yaitu tidak pernah dapat diberi nilai null
. Dalam kode di atas, parameter x
dari log()
diasumsikan bukan nol. Jadi, NullAway melaporkan kesalahan berikut:
warning: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
log(null);
^
Kita dapat memperbaiki kesalahan ini dengan mengizinkan null
diteruskan ke log()
, dengan anotasi @Nullable
:
static void log ( @ Nullable Object x ) {
System . out . println ( x . toString ());
}
Dengan anotasi ini, NullAway menunjukkan kemungkinan dereferensi nol:
warning: [NullAway] dereferenced expression x is @Nullable
System.out.println(x.toString());
^
Kita dapat memperbaiki peringatan ini dengan menambahkan tanda centang nol:
static void log ( @ Nullable Object x ) {
if ( x != null ) {
System . out . println ( x . toString ());
}
}
Dengan perubahan ini, semua peringatan NullAway telah diperbaiki.
Untuk detail lebih lanjut tentang pemeriksaan, pesan kesalahan, dan batasan NullAway, lihat panduan terperinci kami.
Silakan membuka masalah GitHub jika Anda memiliki pertanyaan tentang cara menggunakan NullAway. Atau, Anda dapat bergabung dengan server NullAway Discord dan mengajukan pertanyaan kepada kami di sana.
Kami ingin Anda berkontribusi pada NullAway! Harap perhatikan bahwa setelah Anda membuat permintaan penarikan, Anda akan diminta untuk menandatangani Perjanjian Lisensi Kontributor Uber kami.
NullAway dilisensikan di bawah lisensi MIT. Lihat file LICENSE.txt untuk informasi lebih lanjut.