Neden finalize () uygularsınız?


371

Ben çaylak Java soruları bir sürü üzerinden okuyordum finalize()ve kimsenin gerçekten kesin hale getirdiğini şaşkınlık buluyorum () sonlandırmak () kaynakları temizlemek için güvenilir olmayan bir yoludur. Birinin Bağlantıları temizlemek için kullandığını yorumladığını gördüm, bu gerçekten korkutucu çünkü bir Bağlantı'nın kapalı olduğunu garanti etmenin tek yolu sonunda denemek (yakalamak) uygulamaktır.

CS'de eğitim görmedim, ancak Java'da profesyonel olarak on yıldan fazla bir süredir programlıyorum ve hiç kimsenin finalize()bir üretim sisteminde uygulandığını hiç görmedim . Bu hala kullanımlarının olmadığı veya birlikte çalıştığım insanların doğru yaptığı anlamına gelmez.

Benim sorum şu finalize()ki, başka bir işlem veya dil içindeki sözdizimi yoluyla daha güvenilir bir şekilde ele alınamayan uygulama için hangi kullanım durumları var ?

Lütfen belirli bir senaryo ya da deneyiminizi sağlayın, sadece bir Java ders kitabını tekrarlayın ya da sonlandırmanın amaçlanan kullanımı bu sorunun amacı gibi yeterli değildir.


HI finalize () yöntemi burada çok iyi açıklanmıştır howtodoinjava.com/2012/10/31/…
Sameer Kazi

2
Çoğu uygulama ve kütüphane kodu asla kullanılmaz finalize(). Bununla birlikte, yerel kaynakları arayan adına yöneten platform kitaplığı kodu , SocketInputStreamkaynak kaçağı riskini en aza indirmeye çalışır (veya PhantomReferencedaha sonra eklenen gibi eşdeğer mekanizmaları kullanır ). , geliştiricilerin% 99,9999'u asla bir tane yazmayacak olsa da.
Brian Goetz

Yanıtlar:


231

Harici bir kaynağı (soket, dosya vb.) Tutan bir nesne için geri döndürme noktası olarak kullanabilirsiniz. Çağrılması gereken bir close()yöntem ve belge uygulayın.

İşlemin tamamlanmadığını tespit ederseniz finalize(), close()işlemi gerçekleştirin. Belki stderrbir adam araptan sonra temizlediğinizi belirtmek için bir şey atıldı .

İstisnai / hatalı bir durumda ekstra güvenlik sağlar. Her arayan try {} finally {}her seferinde doğru şeyi yapmayacaktır . Talihsiz, ama çoğu ortamda doğrudur.

Nadiren gerekli olduğuna katılıyorum. Ve yorum yapanların işaret ettiği gibi, GC ek yükü ile geliyor. Sadece uzun süren bir uygulamada bu "kemer ve jartiyer" güvenliğine ihtiyacınız varsa kullanın.

Java 9'dan itibaren Object.finalize()kullanımdan kaldırıldığını görüyorum ! Onlar bize gelin java.lang.ref.Cleanerve java.lang.ref.PhantomReferencealternatif olarak.


44
Finalize () yöntemiyle hiçbir zaman bir istisna oluşturulmadığından emin olun, yoksa çöp toplayıcı bu nesneyi temizlemeye devam etmez ve bir bellek sızıntısı alırsınız.
skaffman

17
Sonlandırmanın çağrılması garanti edilmez, bu nedenle bir kaynak yayınlamaya güvenmeyin.
flicken

19
skaffman - Buna inanmıyorum (bazı hatalı JVM uygulamalarının yanı sıra). Object.finalize () javadoc'dan: Sonlandırma yöntemi tarafından yakalanmamış bir kural dışı durum atılırsa, kural dışı durum yok sayılır ve söz konusu nesnenin sonlandırması sona erer.
John M

4
Teklifiniz, insanların hatalarını (yakın arama yapmadan) uzun süre gizleyebilir. Bunu tavsiye etmem.
kohlerm

64
Aslında tam da bu nedenle kesinleştirme kullandım. Kodu devralmıştım ve çok adamcağız ve veritabanı bağlantılarını açık bırakma eğilimi vardı. Bağlantıları, ne zaman ve nerede oluşturulduğuna ilişkin verileri içerecek şekilde değiştirdik ve daha sonra bağlantı düzgün şekilde kapatılmadıysa bu bilgileri günlüğe kaydetmek için sonlandırmayı uyguladık. Kapalı olmayan bağlantıları izlemek için büyük bir yardım olduğu ortaya çıktı.
brainimus

174

finalize()JVM'ye, kodunuzu belirtilmemiş bir zamanda yürütmenin iyi olabileceğine dair bir ipucudur. Kodun gizemli bir şekilde çalışmamasını istediğinizde bu iyidir.

Sonlandırıcılarda önemli bir şey yapmak (temel olarak kayıt dışında herhangi bir şey) üç durumda da iyidir:

  • diğer kesinleşmiş nesnelerin hala programınızın geri kalanının geçerli kabul ettiği bir durumda olacağını kumar oynamak istersiniz.
  • sonlandırmadan sonra doğru davrandıklarından emin olmak için bir sonlandırıcı içeren tüm sınıflarınızın tüm yöntemlerine çok sayıda kontrol kodu eklemek istersiniz.
  • kesinleşmiş nesneleri yanlışlıkla yeniden diriltmek ve neden işe yaramadıklarını ve / veya sonunda serbest bırakıldıklarında neden kesinleşmediklerini anlamaya çalışmak için çok zaman harcamak istersiniz.

Finalize () ihtiyacınız olduğunu düşünüyorsanız, bazen gerçekten istediğiniz şey bir hayalet referanstır (verilen örnekte, referandı tarafından kullanılan bir bağlantıya sert bir referans tutabilir ve fantom referansı sıraya alındıktan sonra kapatabilir). Bu, gizemli bir şekilde asla çalışamayacağı özelliğe de sahiptir, ancak en azından nihai nesneler üzerinde yöntemleri çağıramaz veya dirilemez. Bu nedenle, bu bağlantıyı temiz bir şekilde kapatmanız gerekmediği durumlar için doğru, ancak oldukça istersiniz ve sınıfınızın müşterileri kendilerini kapatamaz veya yapmayacaklardır (aslında yeterince adil - ne' toplamadan önce belirli bir işlem gerektiren arayüzler tasarlarsanız, çöp toplayıcıya sahip olmanız gereken nokta var mı? Bu bizi malloc / free günlerinde geri getiriyor.)

Diğer zamanlarda daha sağlam olabilmek için yönettiğinizi düşündüğünüz kaynağa ihtiyacınız vardır. Örneğin, neden bu bağlantıyı kapatmanız gerekiyor? Nihayetinde sistem tarafından sağlanan bir tür G / Ç'ye dayanmalıdır (soket, dosya, ne olursa olsun), bu yüzden neden en düşük kaynak seviyesi kullanıldığında sistemi kapatmak için sisteme güvenmiyorsunuz? Diğer uçtaki sunucu kesinlikle soketi düşürmektense bağlantıyı temiz bir şekilde kapatmanızı gerektiriyorsa, birisi kodunuzun çalıştığı makinenin güç kablosundan geçtiğinde veya müdahale eden ağ dışarı çıktığında ne olur?

Feragatname: Geçmişte bir JVM uygulaması üzerinde çalıştım. Sonlandırıcılardan nefret ediyorum.


76
Aşırı alay adaleti için oy.
Algılama

32
Bu soruya cevap vermiyor; sadece finalize()birisinin gerçekten kullanmak isteyebileceği herhangi bir neden vermeden dezavantajlarını söylüyor .
Mekanik salyangoz

1
@supercat: fantom referansları (bu konuda tüm referanslar) Java 2'de tanıtıldı
Steve Jessop

1
@supercat: üzgünüm evet, "referanslar" ile demek istedim java.lang.ref.Referenceve onun alt sınıfları. Java 1'in değişkenleri vardı :-) Ve evet, de finalizörleri vardı.
Steve Jessop

2
@SteveJessop: Bir temel sınıf kurucusu diğer varlıklardan yapım aşamasında olan nesne adına durumlarını değiştirmelerini isterse (çok yaygın bir kalıp), ancak türetilmiş bir sınıf başlatıcı bir istisna atarsa, kısmen oluşturulmuş nesne hemen temizlenmelidir kendisinden sonra (yani hizmetlerine artık gerek duyulmayan dış varlıkları bilgilendirin), ancak ne Java ne de .NET, bunun gerçekleşebileceği herhangi bir uzaktan temiz kalıbı sunmaz. Gerçekten de, temizleme koduna ulaşması için temizliğe ihtiyaç duyan şeye başvurmayı zorlaştırmak için kendi yollarından çıkıyor gibi görünüyorlar.
supercat

58

Basit bir kural: asla sonlandırıcı kullanmayın.

Bir nesnenin bir sonlandırıcıya sahip olması (hangi kodu çalıştırdığına bakılmaksızın) tek başına, çöp toplama için önemli miktarda ek yüke neden olmak için yeterlidir.

Brian Goetz'in bir makalesinden :

Sonlandırıcıları olan nesneler (önemsiz olmayan bir sonlandırma () yöntemine sahip olanlar), sonlandırıcıları olmayan nesnelere kıyasla önemli ölçüde ek yüke sahiptir ve az kullanılmalıdır. Sonlandırılabilir nesnelerin tahsisi daha yavaştır ve toplanması daha yavaştır. Tahsis sırasında, JVM, sonlandırılabilir nesneleri çöp toplayıcısına kaydetmelidir ve (en azından HotSpot JVM uygulamasında) sonlandırılabilir nesneler, diğer birçok nesneden daha yavaş bir ayırma yolunu izlemelidir. Benzer şekilde, sonlanabilir nesnelerin de toplanması daha yavaştır. Sonlandırılabilir bir nesnenin geri kazanılması için en az iki çöp toplama döngüsü (en iyi durumda) gerekir ve çöp toplayıcı sonlandırıcıyı çağırmak için fazladan iş yapmak zorundadır. Sonuç, nesneleri ayırmak ve toplamak için daha fazla zaman harcamak ve çöp toplayıcı üzerinde daha fazla baskı yapmaktır, çünkü erişilemeyen sonlanabilir nesneler tarafından kullanılan bellek daha uzun süre korunur. Sonlandırıcıların öngörülebilir herhangi bir zaman diliminde veya hatta hiç çalışacağının garanti edilmemesi gerçeğiyle birleştirin ve sonlandırmanın kullanmak için doğru araç olduğu nispeten az sayıda durum olduğunu görebilirsiniz.


46

Üretim kodunda kesinleşmeyi kullandığım tek zaman, belirli bir nesnenin kaynaklarının temizlendiğini kontrol etmekti ve eğer değilse, çok sesli bir mesaj kaydedin. Aslında bunu yapmayı denemedi, düzgün yapılmadıysa çok bağırdı. Oldukça kullanışlı olduğu ortaya çıktı.


35

1998'den beri profesyonel olarak Java yapıyorum ve hiç uygulama yapmadım finalize(). Bir kez değil.


O halde kamu sınıfı nesnesini nasıl yok edebilirim? ADF'de soruna neden oluyor. Temel olarak sayfayı yeniden
yükleyecek

2
@ InfantPro'Aravind 'sonlandırma çağrısı nesneyi kaldırmaz. Bu, JVM'nin çöpün nesnenizi toplayıp toplayıp toplamayacağını çağırmayı seçebileceği bir yöntemdir.
Paul Tomblin

@ PaulTomblin, ohk bu detay için teşekkürler. ADF'de bir sayfayı yenilemek için herhangi bir öneriniz var mı?
InfantPro'Aravind '

@ InfantPro'Aravind 'Hiçbir fikrim yok, hiç ADF kullanılmadı.
Paul Tomblin

28

Kabul edilen cevap iyidir, sadece aslında hiç kullanmadan sonuçlandırma işlevine sahip olmanın bir yolu olduğunu eklemek istedim.

"Referans" sınıflarına bakın. Zayıf referans, Fantom Referans ve Yazılım Referansı.

Bunları tüm nesnelerinize bir referans tutmak için kullanabilirsiniz, ancak YALNIZCA bu referans GC'yi durdurmaz. Bununla ilgili en güzel şey, silindiğinde bir yöntemi çağırmasını sağlayabilirsiniz ve bu yöntemin çağrılması garanti edilebilir.

Sonlandırma gelince: Hangi nesnelerin serbest bırakıldığını anlamak için bir kez sonlandırmayı kullandım. Statik, referans sayma ve benzeri bazı düzgün oyunlar oynayabilirsiniz - ancak sadece analiz içindi, ancak bu gibi kodlara dikkat edin (sadece sonuçlandırmada değil, muhtemelen göreceğiniz yer budur):

public void finalize() {
  ref1 = null;
  ref2 = null;
  othercrap = null;
}

Birinin ne yaptığını bilmediğinin bir işaretidir. Bunun gibi "temizlik" neredeyse hiç gerekli değildir. Sınıf GC'd olduğunda, bu otomatik olarak yapılır.

Bir finalde böyle bir kod bulursanız, onu yazan kişinin kafasının karıştığı garanti edilir.

Başka bir yerde ise, kod kötü bir model için geçerli bir yama olabilir (bir sınıf uzun süre kalır ve bazı nedenlerden dolayı başvurduğu şeyler nesne GC'd olmadan önce manuel olarak serbest bırakılmalıdır). Genellikle bir kişi bir dinleyiciyi ya da bir şeyi kaldırmayı unuttuğu ve nesnelerinin neden GC'd olmadığını anlayamadığı için sadece bahsettiği şeyleri siler ve omuzlarını silkirir ve uzaklaşır.

Asla "Hızlı" şeyleri temizlemek için kullanılmamalıdır.


3
Hayalet referanslar, hangi nesnelerin serbest bırakıldığını takip etmenin daha iyi bir yolu olduğunu düşünüyorum.
Bill Michell

2
şimdiye kadar duydum "zayıf referans" en iyi açıklama sağlamak için upvoting.
sscarduzio

Üzgünüm, bu okumam çok uzun sürdü, ama cevaplara gerçekten güzel bir ektir.
Spencer Kormos

27

Bundan ne yapabileceğinizden emin değilim, ama ...

itsadok@laptop ~/jdk1.6.0_02/src/
$ find . -name "*.java" | xargs grep "void finalize()" | wc -l
41

Bu yüzden Güneş'in kullanılması gereken bazı durumlar bulduğunu düşünüyorum.


12
Sanırım aynı zamanda "Sun geliştiricisi her zaman haklı olacak mı?"
CodeReaper

13
Ancak bu kullanımlardan kaç tanesi finalizegerçekte kullanmaktansa sadece destek veriyor ya da test ediyor?
Mekanik salyangoz

Windows kullanıyorum. Windows'da aynı şeyi nasıl yapardınız?
gparyani

2
@damryfbfnetsi: ack (yüklemeyi deneyin beyondgrep.com yoluyla) chocolatey.org/packages/ack . Veya içindeki Basit Dosyalarda Bul özelliğini kullanın $FAVORITE_IDE.
Brian Cline

21
class MyObject {
    Test main;

    public MyObject(Test t) {    
        main = t; 
    }

    protected void finalize() {
        main.ref = this; // let instance become reachable again
        System.out.println("This is finalize"); //test finalize run only once
    }
}

class Test {
    MyObject ref;

    public static void main(String[] args) {
        Test test = new Test();
        test.ref = new MyObject(test);
        test.ref = null; //MyObject become unreachable,finalize will be invoked
        System.gc(); 
        if (test.ref != null) System.out.println("MyObject still alive!");  
    }
}

====================================

sonuç:

This is finalize

MyObject still alive!

=====================================

Bu nedenle, sonlandırma yönteminde erişilemez bir örneğe erişilmesini sağlayabilirsiniz.


21
Nedense, bu kod beni zombi filmleri hakkında düşündürüyor. Nesnenizi GC ve sonra tekrar ayağa kalkar ...
steveha

yukarıda iyi kodlar. Şimdi nesneye nasıl tekrar ulaşılacağını merak ediyordum.
lwpro2

15
Hayır, yukarıdaki kötü kodlar. sonuçlandırmanın neden kötü olduğunun bir örneği.
Tony

Çağırmanın System.gc();, çöp toplayıcının gerçekten çalışacağının garantisi olmadığını unutmayın . Yığın temizliği GC'nin tamamen takdiridir (belki hala yeterince boş yığın, belki çok fazla parçalanmamış, ...). Yani programcı tarafından alçakgönüllü bir istek "lütfen, beni duyabilir ve kaçabilir misin?" "Şimdi söylediğim gibi koş!" Lingual kelimeler kullandığım için özür dilerim ama JVM GC'nin nasıl çalıştığını söylüyor.
Roland

10

finalize()kaynak sızıntılarını yakalamak için faydalı olabilir. Kaynak kapatılmalı, ancak bir günlük dosyasına kapatılmadığı gerçeğini yazmamalı ve kapatılmalıdır. Bu şekilde, kaynak sızıntısını giderirsiniz ve kendinize bunun olduğunu bilmeniz için bir yol verirsiniz.

1.0 alfa 3'ten (1995) beri Java'da program yapıyorum ve henüz hiçbir şey için kesinleşmeyi geçersiz kılmadım ...


6

Kaynaklarınızı sizin için temizlemek için finalize () yöntemine güvenmemelisiniz. finalize (), o zaman sınıf çöp toplanana kadar çalışmaz. Kaynakları kullanmayı bitirdiğinizde açıkça serbest bırakmak çok daha iyidir.


5

Yukarıdaki cevaplarda bir noktayı vurgulamak için: yalnız GC iş parçacığında sonlandırıcılar yürütülecektir. Geliştiricilerin bazı finalizörlere küçük bir uyku ekledikleri ve kasıtlı olarak dizlerine başka türlü süslü bir 3D demo getirdikleri büyük bir Sun demosunu duydum.

Test env teşhisi hariç, önlemek için en iyisi.

Eckel'in Java'daki Düşüncesi'nin bu konuda iyi bir bölümü var.


4

Hmmm, bir zamanlar mevcut bir havuza iade edilmeyen nesneleri temizlemek için kullandım.

Çok geçtiler, bu yüzden havuza ne zaman güvenli bir şekilde geri verilebileceklerini söylemek imkansızdı. Sorun, çöp toplama sırasında nesneleri biriktirmekten çok daha büyük bir ceza getirmesiydi. Tüm havuzu söküp, her şeyi dinamik hale getirmeden ve onunla yapmadan önce yaklaşık bir ay boyunca üretimde idi.


4

A. Ne yaptığınıza dikkat edin finalize(). Özellikle kaynakların temizlenmesini sağlamak için close () işlevini çağırmak gibi şeyler için kullanıyorsanız. Çalışan java koduna bağlı JNI kitaplıklarının bulunduğu çeşitli durumlarla karşılaştık ve JNI yöntemlerini çağırmak için finalize () yöntemini kullandığımız her durumda, çok kötü java yığın bozulması elde ederiz. Yolsuzluk temel JNI kodunun kendisinden kaynaklanmadı, yerel kütüphanelerde tüm bellek izleri iyiydi. Sadece finalize () yönteminden JNI yöntemlerini çağırmamız gerçeğiydi.

Bu hala yaygın olarak kullanılan bir JDK 1.5 ile oldu.

Bir şeyin daha sonraya kadar yanlış gittiğini öğrenemeyiz, ama sonunda suçlu her zaman JNI çağrılarını kullanan finalize () yöntemiydi.


3

Kaynakları yazarken bir tür "temizleme" yöntemi gerektiren diğer geliştiriciler tarafından kullanılacak kod yazarken. Bazen diğer geliştiriciler temizleme (ya da kapat ya da yok et ya da ne olursa olsun) yöntemini çağırmayı unuturlar. Olası kaynak sızıntılarını önlemek için, yöntemin çağrıldığından emin olmak için sonlandırma yöntemini kontrol edebilirsiniz ve eğer değilse, kendiniz arayabilirsiniz.

Birçok veritabanı sürücüsü bunu Bildirim ve Bağlantı uygulamalarında, yakınlarını aramayı unutan geliştiricilere karşı biraz güvenlik sağlamak için yapar.


2

Düzenleme: Tamam, gerçekten işe yaramıyor. Uyguladım ve bazen başarısız olursa benim için sorun değil, ancak kesinleştirme yöntemini tek bir sefer bile çağırmadı.

Profesyonel bir programcı değilim ama programımda, finalize () kullanmanın iyi bir örneğinin olduğunu düşündüğüm bir durumum var, bu, yok edilmeden önce içeriğini diske yazan bir önbellektir. Yıkım sırasında her seferinde yapılması gerekli olmadığından, sadece programımı hızlandırır, umarım yanlış yapmadım.

@Override
public void finalize()
{
    try {saveCache();} catch (Exception e)  {e.printStackTrace();}
}

public void saveCache() throws FileNotFoundException, IOException
{
    ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("temp/cache.tmp"));
    out.writeObject(cache);
}

Bence önbellek (diske bastıracağınız tipte) iyi bir örnek. Ve sonuçlandırılmasa bile, ter yok.
foo

2

Genel / statik bir yere (ihtiyaç dışında) eklenen şeyleri kaldırmak kullanışlı olabilir ve nesne kaldırıldığında kaldırılması gerekir. Örneğin:

    özel void addGlobalClickListener () {
        poorAwtEventListener = yeni WeakAWTEventListener (bu);

        Toolkit.getDefaultToolkit (). AddAWTEventListener (zayıfAwtEventListener, AWTEvent.MOUSE_EVENT_MASK);
    }

    @Override
    korumalı geçersiz finalize () atar Throwable {
        ) (Super.finalize;

        if (poorAwtEventListener! = null) {
            . Toolkit.getDefaultToolkit () removeAWTEventListener (weakAwtEventListener);
        }
    }

Dinleyicinin kendisine thisyapıcıdan geçirilen örneğe güçlü bir referansı olduğunda , bu örneğe asla erişilemez hale geleceği ve dolayısıyla finalize()hiçbir zaman temizlenmeyeceği için ek çabaya ihtiyaç vardır . Öte yandan, dinleyicinin adından da anlaşılacağı gibi, bu nesneye zayıf bir referansı varsa, bu yapı, gerektiğinde temizlenme riskini taşır. Nesne yaşam döngüleri, uygulama semantiği uygulamak için doğru araç değildir.
Holger

0

iirc - finalize yöntemini pahalı kaynaklar için bir havuzlama mekanizması uygulama aracı olarak kullanabilirsiniz - böylece GC'leri de almazlar.


0

Yan not olarak:

Finalize () işlevini geçersiz kılan bir nesne, özel olarak çöp toplayıcı tarafından işlenir. Genellikle, nesne artık kapsam dışında kaldıktan sonra bir nesne toplama döngüsü sırasında hemen yok edilir. Ancak, sonlandırılabilir nesneler bunun yerine bir sıraya taşınır; burada ayrı sonlandırma iş parçacıkları kuyruğu boşaltır ve her nesne üzerinde finalize () yöntemini çalıştırır. Finalize () yöntemi sona erdiğinde, nesne sonunda bir sonraki döngüde çöp toplama için hazır olacaktır.

Kaynak: java-9'da finalize () kullanımdan kaldırıldı


0

Kaynakların (Dosya, Soket, Akış vb.) Onlarla işimiz bittiğinde kapatılması gerekir. Genellikle ifadeler bölümünde close()çağırdığımız yöntemlere sahiptirler . Bazen birkaç geliştirici tarafından da kullanılabilir, ancak IMO her zaman sonuçlandırılacağının garantisi olmadığından uygun bir yol değildir.finallytry-catchfinalize()

Java 7'de aşağıdakiler gibi kullanılabilecek kaynaklarla deneme ifademiz var :

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
  // Processing and other logic here.
} catch (Exception e) {
  // log exception
} finally {
  // Just in case we need to do some stuff here.
}

Yukarıdaki örnekte, try-with-resource, yöntemi BufferedReaderçağırarak kaynağı otomatik olarak kapatacaktır close(). İstersek , Closeable'i kendi sınıflarımızda da uygulayabilir ve benzer şekilde kullanabiliriz. IMO anlaşılması daha temiz ve basit görünüyor.


0

Şahsen, finalize()nadir bir durum dışında neredeyse hiç kullanmadım : Özel bir genel tip koleksiyonu yaptım finalize()ve aşağıdakileri yapan özel bir yöntem yazdım :

public void finalize() throws Throwable {
    super.finalize();
    if (destructiveFinalize) {
        T item;
        for (int i = 0, l = length(); i < l; i++) {
            item = get(i);
            if (item == null) {
                continue;
            }
            if (item instanceof Window) {
                ((Window) get(i)).dispose();
            }
            if (item instanceof CompleteObject) {
                ((CompleteObject) get(i)).finalize();
            }
            set(i, null);
        }
    }
}

( CompleteObjectEğer nadiren uygulanan uyguladığınızı belirtmenizi sağlar yaptığım bir arayüz Objectyöntemleri gibi #finalize(), #hashCode()ve #clone())

Bu nedenle, kardeş #setDestructivelyFinalizes(boolean)yöntemini kullanarak , koleksiyonumu kullanan program, bu koleksiyona yapılan bir referansın yok edilmesinin, içeriğine yapılan referansları da yok edeceğini ve JVM'yi yanlışlıkla canlı tutabilecek tüm pencereleri atabileceğini garanti edebilir (yardımcı olabilir). Ben de herhangi bir iş parçacığı durdurmayı düşündüm, ama bu yepyeni bir solucan kutusu açtı.


4
Arayan finalize()senin üzerine CompleteObjectYukarıdaki kodda yapmak gibi durumlarda JVM hala çağırabilir gibi, iki kez adlı olabileceğini göstermektedir finalize()bu nesneler aslında ulaşılmaz hale kez hangi nedeniyle kesinleştiği mantığına, olabilir, daha öncefinalize() özel toplama yöntemi aynı anda çağrılır, hatta eşzamanlı olarak. Metodunuzda iplik güvenliğini sağlamak için herhangi bir önlem görmediğimden, bunun farkında değilsiniz…
Holger

0

Kabul edilen cevap, kesinleştirme sırasında bir kaynağı kapatmanın yapılabileceğini listeler.

Ancak bu cevap , en azından JIT derleyicisiyle java8'de, nesneniz tarafından tutulan bir akıştan okumayı bitirmeden önce bazen sonlandırıcının çağrıldığı beklenmedik sorunlarla karşılaştığınızı gösterir.

Yani bu bile durum çağıran sonuçlandırmak istiyorum değil tavsiye edilebilir.


İşlem, iş parçacığı güvenli hale getirilirse, bu da bir zorunluluktur, çünkü kesinleştiriciler keyfi iş parçacıkları tarafından çağrılabilir. Doğru bir şekilde uygulanan iş parçacığı güvenliği, yalnızca yakın işlemi değil, aynı zamanda kaynağı kullanan işlemlerin aynı nesne veya kilit üzerinde eşitlenmesi gerektiğinden, kullanım ve yakın işlem arasında daha erken bir ilişki olur ve bu da çok erken Sonlandırma. Ancak, elbette, tüm kullanım için yüksek bir fiyata ...
Holger
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.