Apakah bidang statis terbuka untuk pengumpulan sampah?

95

Diberikan kelas utilitas hipotetis yang hanya digunakan dalam pengaturan program:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

akankah myObject menjadi sampah yang dikumpulkan ketika tidak lagi digunakan, atau akankah tetap ada selama program berjalan?

Michael Deardeuff
sumber

Jawaban:

112

Variabel statis tidak dapat dipilih untuk pengumpulan sampah saat kelas dimuat. Mereka bisa dikumpulkan ketika masing-masing pemuat kelas (yang bertanggung jawab untuk memuat kelas ini) dikumpulkan untuk sampah.

Lihat JLS Bagian 12.7 Pembongkaran Kelas dan Antarmuka

Sebuah kelas atau antarmuka dapat diturunkan jika dan hanya jika pemuat kelas yang menentukan dapat diklaim kembali oleh pengumpul sampah [...] Kelas dan antarmuka yang dimuat oleh bootstrap loader tidak dapat diturunkan.

bruno conde
sumber
@bruno, Berdasarkan tautan Anda, apakah itu berarti bahwa loader kelas menyimpan referensi ke setiap kelas yang dimuatnya, bahkan jika kelas yang dimuat tidak memiliki anggota statis?
Pacerier
@ Brunoconde, saya rasa itu sebenarnya tidak benar. Tepatnya paragraf mana yang menyatakan itu? (Silakan lanjutkan diskusi di stackoverflow.com/questions/405364/… )
Pacerier
Kapan pemuat kelas akan memenuhi syarat untuk pengumpulan sampah. ?
Rohit Bandil
@RohitBandil - jika tidak dapat dijangkau.
Stephen C
55

Variabel statis direferensikan oleh objek Kelas yang direferensikan oleh ClassLoaders -jadi kecuali ClassLoader menjatuhkan Kelas entah bagaimana (jika itu mungkin) atau ClassLoader itu sendiri menjadi memenuhi syarat untuk koleksi (lebih mungkin - pikirkan unloading webapps) variabel statis (atau sebaliknya, objek yang mereka referensikan) tidak akan dikumpulkan.

Jon Skeet
sumber
1
Apakah Classobjek yang tidak berisi variabel statis dirujuk oleh pemuat kelasnya?
Pacerier
14

Jika Anda ingin objek sementara digunakan untuk inisialisasi statis kemudian dibuang, Anda dapat menggunakan blok inisialisasi statis, mis.

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

karena blok penginisialisasi statis adalah jenis khusus dari metode statis, myObject adalah variabel lokal dan dapat dikumpulkan dari sampah setelah blok selesai dieksekusi.

finnw
sumber
13

myObject adalah referensi dan bukan objek . Sebuah objek secara otomatis dikumpulkan sampah ketika tidak ada referensi yang mengarah padanya karena tidak dapat dijangkau.

Begitu juga objek di balik referensi statis "myObject" bisa menjadi sampah yang dikumpulkan jika Anda dereferensi dengan

myObject = null;

dan tidak ada referensi lain untuk objek ini.

Namun referensi dan variabel statis tetap ada selama program Anda berjalan.

Felix Keil
sumber
Selamat datang di StackOverflow! Mengatur objek ke nullakhir static blockadalah opsi yang layak. Dalam kasus saya, umur objek harus lebih lama dari blok statis. Akhir kegunaan objek itu tidak terlalu konkret; demikian pertanyaan saya tentang pemanfaatan pemulung.
Michael Deardeuff
7

Saya pikir ini menjawab pertanyaan Anda - pada dasarnya tidak kecuali kelas tersebut berasal dari loader kelas khusus dan yang membongkar kelas.

Tom
sumber
0

Kuncinya di sini adalah Pengumpulan Sampah dari instance Kelas yaitu Objek. Instance ClassLoader, pada dasarnya, adalah Object. Jadi, jika objek Classloader tidak dikumpulkan sampahnya, semua referensinya yang disimpan di heap (yaitu, hal statis) hampir tidak akan pernah sampah dikumpulkan. Pengecualiannya adalah String pool.

Jadi sebelum Anda tiba-tiba memutuskan untuk melakukan private static MyGiantClass myGiantObject = new MyGiantClass() Berpikirlah dua kali seperti yang telah saya pelajari dengan cara yang sulit.

ha9u63ar.dll
sumber