Java ile bellek s─▒z─▒nt─▒s─▒ olu┼čturma


Al─▒nan cevaba git


Daha yeni bir r├Âportaj yapt─▒m ve Java ile haf─▒za s─▒z─▒nt─▒s─▒ yaratmam istendi .
S├Âylemeye gerek yok, nas─▒l yaratmaya ba┼člayaca─č─▒m─▒ bile bilmiyordum.

├ľrnek ne olurdu?


3053









Cevap say─▒s─▒n─▒ say: 30






Saf Java'da ger├žek bir bellek s─▒z─▒nt─▒s─▒ (kod ├žal─▒┼čt─▒rarak eri┼čilemeyen ancak hala bellekte depolanan nesneler) olu┼čturman─▒n iyi bir yolu:

  1. Uygulama uzun s├╝ren bir i┼č par├žac─▒─č─▒ olu┼čturur (veya daha h─▒zl─▒ s─▒zd─▒rmak i├žin bir i┼č par├žac─▒─č─▒ havuzu kullan─▒n).
  2. ─░┼č par├žac─▒─č─▒ bir s─▒n─▒f─▒ (iste─če ba─čl─▒ olarak ├Âzel) ClassLoader arac─▒l─▒─č─▒yla y├╝kler.
  3. S─▒n─▒f, geni┼č bir bellek ├Âbe─či ay─▒r─▒r (├Ârn. new byte[1000000] ), Statik bir alanda ona g├╝├žl├╝ bir ba┼čvuru saklar ve sonra bir ThreadLocal i├žinde kendisine bir ba┼čvuru saklar. Ekstra bellek tahsis etmek iste─če ba─čl─▒d─▒r (S─▒n─▒f ├Ârne─čini s─▒zd─▒rmak yeterlidir), ancak s─▒z─▒nt─▒n─▒n daha h─▒zl─▒ ├žal─▒┼čmas─▒n─▒ sa─člayacakt─▒r.
  4. ─░┼č par├žac─▒─č─▒, ├Âzel s─▒n─▒fa veya y├╝klendi─či ClassLoader'a yap─▒lan t├╝m ba┼čvurular─▒ temizler.
  5. Tekrar et.

Bu i┼če yar─▒yor ├ž├╝nk├╝ ThreadLocal, ClassLoader ├Â─česine bir referans tutan Class'a referans tutan nesneye bir referans tutuyor. ClassLoader, s─▒rayla, y├╝kledi─či t├╝m S─▒n─▒flara referans tutar.

(├ľzellikle Java 7'den ├Ânce bir├žok JVM uygulamas─▒nda daha k├Ât├╝yd├╝, ├ž├╝nk├╝ Classes ve ClassLoader'lar do─črudan permgen i├žine tahsis edildi ve hi├žbir zaman GC'd'leri olmad─▒. S─▒n─▒f nesnesinin geri al─▒nmas─▒ndan.)

Bu kal─▒ptaki bir de─či┼čiklik, ThreadLocals'─▒ herhangi bir ┼čekilde kullanan uygulamalar─▒ s─▒k s─▒k yeniden konu┼čland─▒r─▒yorsan─▒z, uygulama kaplar─▒n─▒n (Tomcat gibi) elek gibi bellek s─▒zd─▒rabilmesidir. (Uygulama kab─▒ a├ž─▒kland─▒─č─▒ gibi Konular'─▒ kulland─▒─č─▒ndan ve uygulamay─▒ her seferinde yeniden konu┼čland─▒rd─▒─č─▒n─▒zda yeni bir ClassLoader kullan─▒l─▒r.)

G├╝ncelleme : Bir├žok insan sormaya devam etti─činden, bu davran─▒┼č─▒ eylemde g├Âsteren baz─▒ ├Ârnek kodlar .


2210







Statik alan tutma nesne ba┼čvurusu [esp final field]

 class MemorableClass {
    static final ArrayList list = new ArrayList(100);
}
 

String.intern() Uzun Dize ├ça─čr─▒s─▒

 String str=readString(); // read lengthy string any source db,textbox/jsp etc..
// This will place the string in memory pool from which you can't remove
str.intern();
 

(Kapat─▒lmam─▒┼č) a├ž─▒k ak─▒┼člar (dosya, a─č vb ...)

 try {
    BufferedReader br = new BufferedReader(new FileReader(inputFile));
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}
 

Kapat─▒lmam─▒┼č ba─člant─▒lar

 try {
    Connection conn = ConnectionFactory.getConnection();
    ...
    ...
} catch (Exception e) {
    e.printStacktrace();
}
 

Yerel y├Ântemlerle tahsis edilen bellek gibi JVM'nin ├ž├Âp toplay─▒c─▒s─▒ndan eri┼čilemeyen alanlar

Web uygulamalar─▒nda, baz─▒ nesneler uygulama a├ž─▒k├ža durdurulana veya kald─▒r─▒lana kadar uygulama kapsam─▒nda saklan─▒r.

 getServletContext().setAttribute("SOME_MAP", map);
 

noclassgc IBM JDK'da kullan─▒lmayan s─▒n─▒f ├ž├Âp toplanmas─▒n─▒ ├Ânleyen se├ženek gibi yanl─▒┼č veya uygunsuz JVM se├ženekleri

IBM jdk ayarlar─▒na bak─▒n .


1176







Yap─▒lmas─▒ gereken basit bir ┼čey, bir HashSet'i yanl─▒┼č (veya olmayan) bir ┼čekilde kullanmak hashCode() veya equals() daha sonra "kopyalar─▒" eklemeye devam etmektir . Kopyalar─▒ olmas─▒ gerekti─či gibi g├Ârmezden gelmek yerine, k├╝me yaln─▒zca b├╝y├╝yecek ve bunlar─▒ kald─▒ramayacaks─▒n─▒z.

Bu k├Ât├╝ anahtarlar─▒n / ├Â─čelerin tak─▒lmas─▒n─▒ istiyorsan─▒z, gibi bir statik alan kullanabilirsiniz.

 class BadKey {
   // no hashCode or equals();
   public final String key;
   public BadKey(String key) { this.key = key; }
}

Map map = System.getProperties();
map.put(new BadKey("key"), "value"); // Memory leak even if your threads die.
 

448







A┼ča─č─▒da standart unutulmu┼č dinleyiciler vakas─▒, statik referanslar, hashpalardaki sahte / de─či┼čtirilebilir anahtarlar veya sadece ya┼čam d├Âng├╝s├╝n├╝ sonland─▒rma ┼čans─▒ olmadan s─▒k─▒┼čm─▒┼č iplikler gibi Java'n─▒n s─▒zd─▒rd─▒─č─▒ a├ž─▒k olmayan bir durum olacakt─▒r.

  • File.deleteOnExit() - her zaman ipi s─▒zd─▒r─▒yor, dize bir alt dize ise, s─▒z─▒nt─▒ daha da k├Ât├╝d├╝r (altta yatan karakter [] de s─▒zd─▒r─▒lm─▒┼č)- Java 7'de alt char[] dizini de kopyalar , bu nedenle sonraki durum ge├žerli de─čildir ; @Daniel, oy i├žin bir ihtiya├ž yok.

En ├žok y├Ânetilmeyen konular─▒n tehlikesini g├Âstermek i├žin konulara yo─čunla┼čaca─č─▒m, sallanmaya bile dokunmak istemiyorum.

  • Runtime.addShutdownHook ve kald─▒rmay─▒n ... ve daha sonra removeShutdownHook ile, ThreadGroup s─▒n─▒f─▒ndaki ba┼člat─▒lmam─▒┼č konulara ili┼čkin toplanamayan bir hata nedeniyle, ThreadGroup'u etkin bir ┼čekilde s─▒zd─▒r─▒yor. JGroup GossipRouter'da s─▒z─▒nt─▒ var.

  • Bir olu┼čturma olu┼čturma, ancak ba┼člatmayan, Thread yukar─▒daki ile ayn─▒ kategoriye giriyor.

  • Bir iplik devral─▒r olu┼čturma ContextClassLoader ve AccessControlContext art─▒ ThreadGroup ve herhangi InheritedThreadLocal onca referanslar s─▒n─▒f y├╝kleyicisi ve t├╝m statik referanslar ve ja-ja taraf─▒ndan y├╝klenen t├╝m s─▒n─▒flar─▒ ile birlikte, potansiyel bir s─▒z─▒nt─▒ vard─▒r. Bu etki ├Âzellikle s├╝per basit bir ThreadFactory aray├╝ze sahip olan t├╝m jucExecutor ├žer├ževesi ile g├Âr├╝lebilir , ancak ├žo─ču geli┼čtirici gizlenme tehlikesiyle ilgili hi├žbir ipucuna sahip de─čildir. Ayr─▒ca ├žok say─▒da k├╝t├╝phane istek ├╝zerine i┼č par├žac─▒─č─▒ ba┼člat─▒r (├žok fazla end├╝stride pop├╝ler k├╝t├╝phane).

  • ThreadLocal ├Ânbelle─če; Bunlar bir├žok durumda k├Ât├╝d├╝r. Herkesin ThreadLocal'a dayanan bir miktar basit ├Ânbellek g├Ârd├╝─č├╝ne eminim, k├Ât├╝ haberler: E─čer i┼č par├žac─▒─č─▒ ClassLoader ba─člam─▒nda beklenenden fazla devam ederse, saf bir k├╝├ž├╝k s─▒z─▒nt─▒d─▒r. Ger├žekten gerekmedik├že ThreadLocal ├Ânbelleklerini kullanmay─▒n.

  • Arayan ThreadGroup.destroy() ThreadGroup hi├žbir konular─▒ kendisi vard─▒r, ama yine de ├žocuk ThreadGroups tutar zaman. ThreadGroup'un ebeveyninden ayr─▒lmas─▒n─▒ ├Ânleyebilecek k├Ât├╝ bir s─▒z─▒nt─▒, ancak t├╝m ├žocuklar numaraland─▒r─▒lamaz hale geldi.

  • WeakHashMap ve de─čeri (in) kullanmak do─črudan anahtara ba┼čvurur. Bu bir y─▒─č─▒n d├Âk├╝m├╝ olmadan bulmak zor bir tanesidir. Bu Weak/SoftReference , korunan nesneye sert bir referansta kalabilecek geni┼čletilmi┼č herkes i├žin ge├žerlidir .

  • Kullanma java.net.URL HTTP (S) protokol├╝ ile ve gelen kayna─č─▒ y├╝klenirken (!). Bu ├Âzel, KeepAliveCache ThreadGroup sisteminde mevcut i┼člevin ba─člam s─▒n─▒f y├╝kleyicisinden s─▒z─▒nt─▒ yapan yeni bir i┼č par├žac─▒─č─▒ yarat─▒yor. Canl─▒ bir iplik olmad─▒─č─▒nda, i┼č par├žac─▒─č─▒ ilk istek ├╝zerine olu┼čturulur, b├Âylece ya ┼čansl─▒ ya da sadece s─▒z─▒nt─▒ alabilirsiniz. S─▒z─▒nt─▒, Java 7'de zaten sabittir ve i┼č par├žac─▒─č─▒ olu┼čturan kod, ba─člam s─▒n─▒f─▒ y├╝kleyiciyi d├╝zg├╝n ┼čekilde kald─▒r─▒r. Birka├ž vaka daha var (ImageFetcher gibi, ayr─▒ca benzer konular─▒ yaratma).

  • Kullan─▒lmas─▒ InflaterInputStream ge├žirilmesi new java.util.zip.Inflater() (kurucusundaki PNGImageDecoder ├Ârne─čin) ve aramayaca─č─▒m end() Inflater ait. Peki, kurucuya sadece bir new ┼čansla girerseniz , hi├žbir ┼čans ... Ve evet, close() el ile yap─▒c─▒ parametresi olarak el ile iletilirse ak─▒nt─▒ya ├ža─čr─▒ verilmesi inflater'─▒ kapatmaz. Bu kesin bir s─▒z─▒nt─▒ de─čil ├ž├╝nk├╝ kesinle┼čtirici taraf─▒ndan gerekli g├Ârd├╝─č├╝ zaman serbest b─▒rak─▒lacak. O ana kadar yerel belle─či o kadar ├žok t├╝ketirse, Linux oom_killer'in i┼člemi durdurmadan ├Âld├╝rmesine neden olabilir. As─▒l mesele, JavaÔÇÖda sonland─▒rman─▒n ├žok g├╝venilmez olmas─▒ ve G1ÔÇÖin 7.0.2ÔÇÖye kadar daha da k├Ât├╝le┼čmesi. Hikayenin ahlaki: m├╝mk├╝n olan en k─▒sa s├╝rede yerel kaynaklar─▒ serbest b─▒rak─▒n; sonland─▒r─▒c─▒ sadece ├žok zay─▒f.

  • Ayn─▒ durum java.util.zip.Deflater . Deflater, Java'da a├ž olan bir bellek oldu─čundan, bu daha k├Ât├╝d├╝r, yani her zaman 15 bit (maks) ve 8 bellek seviyesi (9 maks.) Kullan─▒r ve y├╝zlerce KB yerel bellek ay─▒r─▒r. Neyse ki, Deflater yayg─▒n olarak kullan─▒lm─▒yor ve bildi─čim kadar─▒yla JDK k├Ât├╝ye kullanma i├žermiyor. end() El ile Deflater veya olu┼čturdu─čunuzda her zaman aray─▒n Inflater . Son ikisinin en iyi k─▒sm─▒: onlar─▒ mevcut normal profilleme ara├žlar─▒yla bulam─▒yorsun.

(─░stek ├╝zerine kar┼č─▒la┼čt─▒─č─▒m daha fazla zaman kayb─▒n─▒ ekleyebilirim.)

─░yi ┼čanslar selametle; s─▒z─▒nt─▒lar k├Ât├╝d├╝r!


264







Buradaki ├žo─ču ├Ârnek "├žok karma┼č─▒k". Onlar kenar davalar─▒. Bu ├Ârneklerle, programc─▒ bir hata yapt─▒ (e┼čittir / hashcode'u yeniden tan─▒mlam─▒yor gibi) veya JVM / JAVA'n─▒n (statik i├žeren s─▒n─▒f y├╝k├╝ ...) bir k├Â┼če davas─▒ taraf─▒ndan ─▒s─▒r─▒ld─▒. Bence bu bir g├Âr├╝┼čmecinin istedi─či bir ├Ârnek de─čil, hatta en yayg─▒n vaka.

Ancak bellek s─▒z─▒nt─▒lar─▒ i├žin ger├žekten daha basit durumlar vard─▒r. ├ç├Âp toplay─▒c─▒ yaln─▒zca art─▒k referans al─▒nmayan─▒ serbest b─▒rak─▒r. Java geli┼čtiricileri olarak haf─▒zay─▒ umursam─▒yoruz. Gerekti─činde tahsis ediyoruz ve otomatik olarak serbest b─▒rak─▒l─▒yor. ─░nce.

Ancak herhangi bir uzun ├Âm├╝rl├╝ ba┼čvuru payla┼č─▒lan devlet e─čilimindedir. Her ┼čey olabilir, statik, singleton ... Genellikle ├Ânemsiz olmayan uygulamalar karma┼č─▒k nesneler grafikler yapma e─čilimindedir. Sadece bo┼č bir referans ayarlamay─▒ unutmak ya da daha s─▒k olarak bir nesneyi koleksiyondan kald─▒rmay─▒ unutmak, bellek s─▒z─▒nt─▒s─▒ yapmak i├žin yeterlidir.

Elbette her t├╝rl├╝ dinleyici (UI dinleyicileri gibi), ├Ânbellek veya uzun ├Âm├╝rl├╝ payla┼č─▒lan bir durum, do─čru ┼čekilde kullan─▒lmazsa bellek s─▒z─▒nt─▒s─▒ ├╝retme e─čilimindedir. Anla┼č─▒lmas─▒ gereken, bunun bir Java k├Â┼če davas─▒ olmad─▒─č─▒ veya ├ž├Âp toplay─▒c─▒ ile ilgili bir sorun olmad─▒─č─▒d─▒r. Bu bir tasar─▒m problemi. Uzun ├Âm├╝rl├╝ bir nesneye bir dinleyici ekledi─čimizi tasarl─▒yoruz, ancak art─▒k gerekmedi─činde dinleyiciyi ├ž─▒karm─▒yoruz. Nesneleri ├Ânbelle─če al─▒yoruz, ancak ├Ânbellekten kald─▒rma stratejimiz yok.

Belki de bir hesaplama i├žin gereken ├Ânceki durumu saklayan karma┼č─▒k bir grafi─če sahibiz. Ancak ├Ânceki durumun kendisi, daha ├Ânce vb. Devlete ba─čl─▒d─▒r.

Mesela SQL ba─člant─▒lar─▒n─▒ veya dosyalar─▒ kapatmam─▒z gerekiyor. ├ľ─čeleri null toplama ve toplama i├žin uygun referanslar belirlememiz gerekir. Uygun ├Ânbellekleme stratejilerine sahip olaca─č─▒z (maksimum bellek boyutu, ├Â─če say─▒s─▒ veya zamanlay─▒c─▒lar). Bir dinleyicinin bilgilendirilmesine izin veren t├╝m nesneler hem addListener hem de removeListener y├Ântemi sa─člamal─▒d─▒r. Ve bu bildiriciler art─▒k kullan─▒lmad─▒─č─▒nda, dinleyici listelerini silmeliler.

Bir bellek s─▒z─▒nt─▒s─▒ ger├žekten m├╝mk├╝n ve m├╝kemmel bir ┼čekilde tahmin edilebilir. ├ľzel dil ├Âzelliklerine veya k├Â┼če k─▒l─▒flar─▒na gerek yok. Bellek s─▒z─▒nt─▒s─▒ ya bir ┼čeyin eksik olabilece─činin ya da tasar─▒m sorunlar─▒n─▒n bir g├Âstergesidir.


192







Cevap tamamen g├Âr├╝┼čmecinin ne istedi─čini d├╝┼č├╝nd├╝─č├╝ne ba─čl─▒d─▒r.

Java s─▒z─▒nt─▒s─▒ yapmak pratikte m├╝mk├╝n m├╝? Elbette ├Âyle ve di─čer cevaplarda da pek ├žok ├Ârnek var.

Ancak, sorulabilecek birden fazla meta soru var m─▒?

  • Teorik olarak "m├╝kemmel" bir Java uygulamas─▒ s─▒z─▒nt─▒lara kar┼č─▒ savunmas─▒z m─▒d─▒r?
  • Aday teori ile ger├žeklik aras─▒ndaki fark─▒ anl─▒yor mu?
  • Aday ├ž├Âp toplaman─▒n nas─▒l ├žal─▒┼čt─▒─č─▒n─▒ anl─▒yor mu?
  • Veya ideal bir durumda ├ž├Âp toplaman─▒n nas─▒l ├žal─▒┼čmas─▒ gerekiyor?
  • Ba┼čka dilleri yerel aray├╝zlerden arayabildiklerini biliyorlar m─▒?
  • Di─čer dillerde haf─▒za s─▒zd─▒rmay─▒ biliyorlar m─▒?
  • Aday, bellek y├Ânetiminin ne oldu─čunu ve Java'daki sahnenin arkas─▒nda neler oldu─čunu biliyor mu?

Meta sorunuzu "Bu r├Âportajda kullanabilece─čim bir cevap nedir" olarak okuyorum. Ve b├Âylece, Java yerine r├Âportaj becerilerine odaklanaca─č─▒m. Bir r├Âportajda bir sorunun cevab─▒n─▒ bilmeme durumunu tekrarlama olas─▒l─▒─č─▒n─▒z─▒n, Java s─▒z─▒nt─▒s─▒n─▒ nas─▒l yapaca─č─▒n─▒z─▒ bilmeniz gereken bir yerde olman─▒zdan daha muhtemel oldu─čuna inan─▒yorum. Yani, umar─▒m, bu yard─▒mc─▒ olacakt─▒r.

G├Âr├╝┼čme i├žin geli┼čtirebilece─činiz en ├Ânemli becerilerden biri, sorular─▒ aktif olarak dinlemeyi ├Â─črenmek ve g├Âr├╝┼čmeciyle niyetlerini ortaya ├ž─▒karmak i├žin ├žal─▒┼čmakt─▒r. Bu, onlar─▒n sorusunu istedikleri gibi cevaplaman─▒za izin vermekle kalmaz, ayn─▒ zamanda baz─▒ hayati ileti┼čim becerilerine sahip oldu─čunuzu g├Âsterir. Pek ├žok e┼čit yetenekli geli┼čtirici aras─▒nda bir se├žim yap─▒ld─▒─č─▒nda, her seferinde cevap vermeden ├Ânce dinleyen, d├╝┼č├╝nen ve anlayan birini i┼če alaca─č─▒m.


155







Anlamad─▒─č─▒n─▒z a┼ča─č─▒dakiler, bir ├žok anlams─▒z ├Ârnektir JDBC . Veya JDBC yak─▒n bir geli┼čtirici bekledi─čini nas─▒l en az Connection , Statement ve ResultSet onlar─▒ iptal edebilir veya bunlara referanslar─▒ kaybederek yerine uygulanmas─▒ g├╝venmeden ├Ânce ├Ârneklerini finalize .

 void doWork()
{
   try
   {
       Connection conn = ConnectionFactory.getConnection();
       PreparedStatement stmt = conn.preparedStatement("some query"); // executes a valid query
       ResultSet rs = stmt.executeQuery();
       while(rs.hasNext())
       {
          ... process the result set
       }
   }
   catch(SQLException sqlEx)
   {
       log(sqlEx);
   }
}
 

Yukar─▒daki sorun, Connection nesnenin kapal─▒ olmamas─▒ ve dolay─▒s─▒yla ├ž├Âp toplay─▒c─▒ etrafa gelip eri┼čilemez oldu─čunu g├Ârene kadar fiziksel ba─člant─▒n─▒n a├ž─▒k kalmas─▒d─▒r. GC, finalize y├Ântemi ├ža─č─▒r─▒r , ancak uygulanmayan finalize , en az─▒ndan uyguland─▒─č─▒ ┼čekilde uygulama yapmayan JDBC s├╝r├╝c├╝leri vard─▒r Connection.close . Sonu├žta ortaya ├ž─▒kan davran─▒┼č, toplanan eri┼čilemeyen nesneler nedeniyle bellek yeniden kazan─▒l─▒rken, Connection nesne ile ili┼čkilendirilmi┼č kaynaklar─▒n (bellek dahil) basit├že geri kazan─▒lmamas─▒ olabilir.

B├Âyle bir durumda Connection bireyin finalize bir y├Ântem de─čildir temiz yukar─▒ her ┼čeyi yapar, bir ger├žek veritaban─▒ sunucusu sonunda ba─člant─▒ hayatta olmad─▒─č─▒n─▒ ├Â─črenirse kadar veritaban─▒ sunucusuna fiziksel ba─člant─▒ (birka├ž ├ž├Âp toplama d├Âng├╝leri s├╝recek fark edebilirsiniz e─čer o yapar) ve kapat─▒lmal─▒d─▒r.

JDBC s├╝r├╝c├╝s├╝ uygulansa finalize bile, sonland─▒rma s─▒ras─▒nda istisnalar at─▒labilir. Sonu├žta ortaya ├ž─▒kan davran─▒┼č, ┼ču anda "uykuda olan" nesne ile ili┼čkili herhangi bir belle─čin, finalize yaln─▒zca bir kez ├ža─čr─▒lmas─▒n─▒n garanti edildi─či gibi geri kazan─▒lmayaca─č─▒d─▒r .

Nesne sonland─▒rmas─▒ s─▒ras─▒nda istisnalarla kar┼č─▒la┼čman─▒n yukar─▒daki senaryosu, muhtemelen bellek s─▒z─▒nt─▒s─▒na - nesne yeniden dirilmesine neden olabilecek ba┼čka bir senaryo ile ilgilidir. Nesne dirili┼či, genellikle ba┼čka bir nesneden nesneye sonland─▒r─▒lmas─▒ndan dolay─▒ g├╝├žl├╝ bir referans olu┼čturularak kas─▒tl─▒ olarak yap─▒l─▒r. Nesne dirili┼či yanl─▒┼č kullan─▒ld─▒─č─▒nda, di─čer bellek s─▒z─▒nt─▒ kaynaklar─▒ ile birlikte bir bellek s─▒z─▒nt─▒s─▒na yol a├žacakt─▒r.

Bir araya getirebilece─činiz ├žok say─▒da ├Ârnek var -

  • List Yaln─▒zca listeye ekledi─činiz ve silmeyece─činiz bir ├Ârne─či y├Ânetme (art─▒k gerek duymad─▒─č─▒n─▒z ├Â─čelerden kurtulman─▒z gerekir), veya
  • Socket S veya File s'yi a├žma , ancak art─▒k gerekmedi─činde onlar─▒ kapatma ( Connection s─▒n─▒f─▒ i├žeren yukar─▒daki ├Ârne─če benzer ┼čekilde ).
  • Bir Java EE uygulamas─▒n─▒ indirirken Singletons'─▒ bo┼čaltma. G├Âr├╝n├╝┼če g├Âre, singleton s─▒n─▒f─▒n─▒ y├╝kleyen Classloader, s─▒n─▒fa referans─▒ koruyacak ve dolay─▒s─▒yla singleton ├Ârne─či asla toplanmayacak. Uygulaman─▒n yeni bir ├Ârne─či da─č─▒t─▒ld─▒─č─▒nda, genellikle yeni bir s─▒n─▒f y├╝kleyici olu┼čturulur ve singleton nedeniyle eski s─▒n─▒f y├╝kleyici varl─▒─č─▒n─▒ s├╝rd├╝rmeye devam eder.

128







Muhtemelen olas─▒ bir bellek s─▒z─▒nt─▒s─▒n─▒n en basit ├Ârneklerinden biri ve bunun nas─▒l ├Ânlenebilece─či ArrayList.remove (int) 'in uygulanmas─▒d─▒r:

 public E remove(int index) {
    RangeCheck(index);

    modCount++;
    E oldValue = (E) elementData[index];

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index + 1, elementData, index,
                numMoved);
    elementData[--size] = null; // (!) Let gc do its work

    return oldValue;
}
 

Kendiniz uygularsan─▒z, art─▒k kullan─▒lmayan dizi eleman─▒n─▒ temizlemeyi d├╝┼č├╝n├╝r m├╝s├╝n├╝z ( elementData[--size] = null )? Bu referans b├╝y├╝k bir nesneyi canl─▒ tutabilir ...


117







Art─▒k ihtiya├ž duymad─▒─č─▒n─▒z nesnelere yap─▒lan referanslar─▒ saklad─▒─č─▒n─▒z zaman bir bellek s─▒z─▒nt─▒s─▒ ya┼čars─▒n─▒z. Bellek s─▒z─▒nt─▒lar─▒n─▒n Java'da kendini nas─▒l g├Âsterdi─či ve bu konuda ne yapabilece─činiz konusunda ├Ârnekler i├žin Java programlar─▒ndaki bellek s─▒z─▒nt─▒lar─▒n─▒ kullanma b├Âl├╝m├╝ne bak─▒n .


65







Sun.misc.Unsafe s─▒n─▒f─▒ ile bellek s─▒z─▒nt─▒s─▒ yapabilirsiniz . Asl─▒nda bu hizmet s─▒n─▒f─▒ farkl─▒ standart s─▒n─▒flarda kullan─▒l─▒r (├Ârne─čin, java.nio s─▒n─▒flar─▒nda). Bu s─▒n─▒f─▒n ├Ârne─čini do─črudan olu┼čturamazs─▒n─▒z , ancak bunu yapmak i├žin yans─▒ma kullanabilirsiniz .

Kod Eclipse IDE'de javac derlenmiyor - komutunu kullanarak derleyin (derleme s─▒ras─▒nda uyar─▒lar al─▒rs─▒n─▒z)

 import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import sun.misc.Unsafe;


public class TestUnsafe {

    public static void main(String[] args) throws Exception{
        Class unsafeClass = Class.forName("sun.misc.Unsafe");
        Field f = unsafeClass.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe unsafe = (Unsafe) f.get(null);
        System.out.print("4..3..2..1...");
        try
        {
            for(;;)
                unsafe.allocateMemory(1024*1024);
        } catch(Error e) {
            System.out.println("Boom :)");
            e.printStackTrace();
        }
    }

}
 

49







Cevab─▒m─▒ buradan kopyalayabilirim: Java'da bellek s─▒z─▒nt─▒s─▒na neden olman─▒n en kolay yolu?

"Bilgisayar bilimlerinde (veya bu ba─člamda s─▒z─▒nt─▒ olmak ├╝zere) bir bellek s─▒z─▒nt─▒s─▒, bir bilgisayar program─▒ belle─či t├╝ketti─činde ancak i┼čletim sistemine geri veremedi─činde ortaya ├ž─▒kar." (Vikipedi)

Kolay cevap: Yapamazs─▒n. Java otomatik bellek y├Ânetimini yapar ve sizin i├žin gerekmeyen kaynaklar─▒ serbest b─▒rak─▒r. Bunun olmas─▒n─▒ engelleyemezsin. HER ZAMAN kaynaklar─▒ serbest b─▒rakabilecek. Manuel bellek y├Ânetimi olan programlarda bu farkl─▒d─▒r. Malloc () kullanarak C de bir miktar bellek bulam─▒yorsunuz. Belle─či bo┼čaltmak i├žin, malloc'un d├Ând├╝rd├╝─č├╝ i┼čaret├žiye ve bunun ├╝zerine free () ├ža─čr─▒s─▒ yapman─▒z gerekir. Ancak i┼čaret├žiyi art─▒k kullanm─▒yorsan─▒z (├╝zerine yaz─▒lm─▒┼č veya ├Âm├╝r boyu a┼č─▒lm─▒┼čsa), o zaman ne yaz─▒k ki bu belle─či serbest b─▒rakamazs─▒n─▒z ve bu nedenle de bir bellek s─▒z─▒nt─▒s─▒ ya┼čars─▒n─▒z.

┼×imdiye kadar di─čer t├╝m cevaplar benim tan─▒m─▒mda ger├žekten bellek s─▒z─▒nt─▒s─▒ de─čil. Hepsi haf─▒zay─▒ anlams─▒z ┼čeyler ile h─▒zl─▒ bir ┼čekilde doldurmay─▒ ama├žl─▒yor. Fakat herhangi bir zamanda, yaratt─▒─č─▒n─▒z nesneleri serbest b─▒rakabilir ve b├Âylece belle─či serbest b─▒rakabilirsiniz -> NO LEAK. acconrad'─▒n cevab─▒ olduk├ža yakla┼č─▒yor, ├ž├╝nk├╝ benim ├ž├Âz├╝m├╝, ├ž├Âp toplay─▒c─▒y─▒ sonsuz bir d├Âng├╝ye sokarak zorla ÔÇť├ž├ÂkertmekÔÇŁ.

Uzun cevap: JNI kullanarak Java i├žin bir k├╝t├╝phane yazarak bellek s─▒z─▒nt─▒s─▒ alabilirsiniz; bu, manuel bellek y├Ânetimine sahip olabilir ve bu nedenle bellek s─▒z─▒nt─▒s─▒ olabilir. Bu k├╝t├╝phaneyi ├ža─č─▒r─▒rsan─▒z, java i┼čleminiz bellek s─▒zd─▒r─▒yor. Veya JVM'de hatalar olabilir, b├Âylece JVM belle─či kaybeder. JVM'de muhtemelen b├Âcekler vard─▒r, ├ž├Âp toplama i┼člemi bu kadar ├Ânemsiz olmad─▒─č─▒ i├žin baz─▒ bilinenler bile olabilir, ancak o zaman hala bir hata vard─▒r. Tasar─▒m gere─či bu m├╝mk├╝n de─čildir. B├Âyle bir hatadan etkilenen baz─▒ java kodlar─▒ istiyor olabilirsiniz. ├ťzg├╝n├╝m bir tanesini bilmiyorum ve bir sonraki Java s├╝r├╝m├╝nde art─▒k bir hata olmayabilir.


43







─░┼čte http://wiki.eclipse.org/Performance_Bloopers#String.substring.28.29 arac─▒l─▒─č─▒yla basit / u─čursuz biri .

 public class StringLeaker
{
    private final String muchSmallerString;

    public StringLeaker()
    {
        // Imagine the whole Declaration of Independence here
        String veryLongString = "We hold these truths to be self-evident...";

        // The substring here maintains a reference to the internal char[]
        // representation of the original string.
        this.muchSmallerString = veryLongString.substring(0, 1);
    }
}
 

Alt dize, orijinalin ├žok daha uzun bir dizenin i├ž g├Âsterimini ifade etti─či i├žin, orijinal bellekte kal─▒r. Bu nedenle, oyun s─▒ras─▒nda bir StringLeaker'─▒n─▒z oldu─ču s├╝rece, sadece bir karakterli dizgeye tutunaca─č─▒n─▒z─▒ d├╝┼č├╝nseniz bile, t├╝m orijinal dizgiyi bellekte saklayabilirsiniz.

Orijinal diziye istenmeyen bir referans─▒ saklamaktan ka├ž─▒nman─▒n yolu ┼č├Âyle bir ┼čey yapmakt─▒r:

 ...
this.muchSmallerString = new String(veryLongString.substring(0, 1));
...
 

Daha fazla k├Ât├╝l├╝k .intern() i├žin alt dizeyi de kullanabilirsiniz:

 ...
this.muchSmallerString = veryLongString.substring(0, 1).intern();
...
 

Bunu yapmak, hem orijinal uzun dizeyi hem de t├╝retilmi┼č alt dizeyi, StringLeaker ├Ârne─či at─▒ld─▒ktan sonra bile bellekte tutar.


37







Servlet konteynerinde ├žal─▒┼čan herhangi bir web uygulamas─▒n─▒ al─▒n (Tomcat, Jetty, Glassfish, her neyse ...). Uygulamay─▒ arka arkaya 10 veya 20 kez yeniden konu┼čland─▒r─▒n (sunucunun otomatik da─č─▒t─▒m dizinindeki WAR'ye dokunman─▒z yeterli olabilir.

Herhangi biri bunu ger├žekten test etmediyse, birka├ž yeniden da─č─▒t─▒mdan sonra bir OutOfMemoryError alma ┼čans─▒n─▒z y├╝ksektir, ├ž├╝nk├╝ uygulama kendi kendine temizlik yapmaya ├Âzen g├Âstermedi. Bu test ile sunucunuzda bir hata bile bulabilirsiniz.

Sorun ┼ču ki, kab─▒n kullan─▒m ├Âmr├╝, uygulaman─▒z─▒n kullan─▒m ├Âmr├╝nden daha uzun. Konteyn─▒r─▒n uygulaman─▒zdaki nesnelere veya s─▒n─▒flara sahip olabilece─či t├╝m referanslar─▒n ├ž├Âp toplanabilece─činden emin olmal─▒s─▒n─▒z.

Web uygulaman─▒z─▒n i┼čsizli─činden kurtulan tek bir referans varsa, ilgili s─▒n─▒f y├╝kleyici ve bunun sonucunda web uygulaman─▒z─▒n t├╝m s─▒n─▒flar─▒ ├ž├Âp toplanamaz.

Uygulaman─▒z taraf─▒ndan ba┼člat─▒lan ba┼čl─▒klar, ThreadLocal de─či┼čkenleri, g├╝nl├╝k kayd─▒ ekleri, s─▒n─▒f y├╝kleyici s─▒z─▒nt─▒s─▒na neden olan ola─čan ┼č├╝phelilerden baz─▒lar─▒d─▒r.


35







Bunun GUI kodundaki yayg─▒n bir ├Ârne─či, bir widget / bile┼čen olu┼čturup baz─▒ statik / uygulama kapsam─▒ndaki nesnelere bir dinleyici eklerken ve ard─▒ndan widget yok edildi─činde dinleyiciyi ├ž─▒karmamakt─▒r. Sadece bellek s─▒z─▒nt─▒s─▒ almakla kalmaz, ayn─▒ zamanda ne olaylar─▒ dinlerseniz dinlersiniz, t├╝m eski dinleyicileriniz de denir.


35







Belki JNI ├╝zerinden harici yerel kod kullanarak?

Saf Java ile neredeyse imkans─▒zd─▒r.

Ancak, art─▒k belle─če art─▒k eri┼čemedi─činiz zaman, ÔÇťstandartÔÇŁ bir bellek s─▒z─▒nt─▒s─▒ hakk─▒nda, ancak yine de uygulamaya aittir. Bunun yerine kullan─▒lmayan nesnelere referanslar saklayabilir veya daha sonra kapatmadan ak─▒┼člar─▒ a├žabilirsiniz.


33







PermGen ve XML ayr─▒┼čt─▒rma ile ilgili bir kez g├╝zel bir "bellek s─▒z─▒nt─▒s─▒" oldu. Kar┼č─▒la┼čt─▒─č─▒m─▒z─▒ daha h─▒zl─▒ yapmak i├žin kulland─▒─č─▒m─▒z XML ayr─▒┼čt─▒r─▒c─▒s─▒ (hangisinin oldu─čunu hat─▒rlam─▒yorum) bir String.intern () etiketi yapm─▒┼čt─▒r. M├╝┼čterilerimizden biri, veri de─čerlerini XML ├Âzniteliklerinde veya metinlerinde de─čil, tagnames olarak saklamak konusunda harika fikirlere sahipti.

 <data>
   <1>bla</1>
   <2>foo</>
   ...
</data>
 

Asl─▒nda, say─▒lar─▒ kullanmad─▒lar, ancak g├╝nde 10 ila 15 milyon aras─▒nda bir say─▒daki benzersiz ve daha uzun metin kimliklerini (yakla┼č─▒k 20 karakter) kulland─▒lar. G├╝nde 200 MB'l─▒k bir ├ž├Âp yapar, bu asla tekrar gerekli de─čildir ve asla GCed (PermGen'de oldu─čundan). Permgen 512 MB olarak ayarland─▒, bu y├╝zden haf─▒za d─▒┼č─▒ istisnalar─▒n (OOME) ula┼čmas─▒ iki g├╝n s├╝rd├╝.


29







Bellek s─▒z─▒nt─▒s─▒ nedir:

  • Bu bir sebep oluyor hata veya k├Ât├╝ tasar─▒m.
  • Bu bir haf─▒za kayb─▒.
  • Zamanla daha da k├Ât├╝le┼čiyor.
  • ├ç├Âp toplay─▒c─▒ temizleyemez.

Tipik ├Ârnek:

Nesnelerin ├Ânbelle─či i┼čleri kar─▒┼čt─▒rmak i├žin iyi bir ba┼člang─▒├ž ÔÇőÔÇőnoktas─▒d─▒r.

 private static final Map<String, Info> myCache = new HashMap<>();

public void getInfo(String key)
{
    // uses cache
    Info info = myCache.get(key);
    if (info != null) return info;

    // if it's not in cache, then fetch it from the database
    info = Database.fetch(key);
    if (info == null) return null;

    // and store it in the cache
    myCache.put(key, info);
    return info;
}
 

├ľnbellek b├╝y├╝r ve b├╝y├╝r. Ve ├žok ge├žmeden t├╝m veritaban─▒ haf─▒zaya g├Âm├╝l├╝yor. Daha iyi bir tasar─▒m LRUMap kullan─▒r (Sadece son kullan─▒lan nesneleri ├Ânbellekte tutar).

Elbette, i┼čleri daha karma┼č─▒k hale getirebilirsiniz:

  • ThreadLocal yap─▒lar─▒ kullanarak .
  • daha karma┼č─▒k referans a─ča├žlar─▒ ekleyerek .
  • veya 3. parti k├╝t├╝phanelerinin neden oldu─ču s─▒z─▒nt─▒lar .

Ne s─▒kl─▒kta olur:

Bu Bilgi nesnesinde, ba┼čka nesnelere referanslar varsa, yine ba┼čka nesnelere referanslar vard─▒r. Bir ┼čekilde, bunun da bir ├že┼čit bellek s─▒z─▒nt─▒s─▒ oldu─čunu d├╝┼č├╝nebilirsiniz (k├Ât├╝ tasar─▒m nedeniyle).


23







─░├ž s─▒n─▒fta hi├ž kimsenin kullan─▒lmamas─▒n─▒n ilgin├ž oldu─čunu d├╝┼č├╝nd├╝m. Dahili bir s─▒n─▒f─▒n─▒z varsa; do─čal olarak i├žeren s─▒n─▒fa yap─▒lan bir referans─▒ korur. Elbette teknik olarak bir bellek s─▒z─▒nt─▒s─▒ de─čildir, ├ž├╝nk├╝ Java WILL sonunda temizler; ancak bu, s─▒n─▒flar─▒n beklenenden daha uzun s├╝re dayanmas─▒na neden olabilir.

 public class Example1 {
  public Example2 getNewExample2() {
    return this.new Example2();
  }
  public class Example2 {
    public Example2() {}
  }
}
 

┼×imdi ├ľrnek1'i aray─▒p ├ľrnek1'i atmadan bir ├ľrnek2 al─▒rsan─▒z, ├Âz├╝nde hala bir ├ľrnek1 nesnesine bir ba─č─▒n─▒z olacakt─▒r.

 public class Referencer {
  public static Example2 GetAnExample2() {
    Example1 ex = new Example1();
    return ex.getNewExample2();
  }

  public static void main(String[] args) {
    Example2 ex = Referencer.GetAnExample2();
    // As long as ex is reachable; Example1 will always remain in memory.
  }
}
 

Ayr─▒ca, belirli bir s├╝reden daha uzun s├╝re var olan bir de─či┼čkeniniz varsa, s├Âylentileri duydum; Java, her zaman var olaca─č─▒n─▒ ve kodda art─▒k ula┼č─▒lam─▒yorsa, onu asla temizlemeye ├žal─▒┼čmayaca─č─▒n─▒ varsaymaktad─▒r. Ancak bu tamamen do─črulanmam─▒┼č.


22







Ge├ženlerde log4j neden oldu─ču bir bellek s─▒z─▒nt─▒s─▒ durumuyla kar┼č─▒la┼čt─▒m.

Log4j, interleaved log ├ž─▒kt─▒s─▒n─▒ farkl─▒ kaynaklardan ay─▒rt etmek i├žin bir ara├ž olan Nested Diagnostic Context (NDC) olarak adland─▒r─▒lan bu mekanizmaya sahiptir . NDC'nin ├žal─▒┼čt─▒─č─▒ ayr─▒nt─▒ d├╝zeyi i┼č par├žac─▒klar─▒d─▒r, bu nedenle g├╝nl├╝k ├ž─▒kt─▒lar─▒n─▒ farkl─▒ i┼č par├žac─▒klar─▒ndan ayr─▒ olarak ay─▒r─▒r.

─░┼č par├žac─▒─č─▒na ├Âzg├╝ etiketleri saklamak i├žin, log4j'nin NDC s─▒n─▒f─▒, Thread nesnesinin (thread kimli─čini s├Âylemek yerine) anahtarlanm─▒┼č bir Hashtable'─▒ kullan─▒r ve b├Âylece NDC etiketi, i┼č par├žac─▒─č─▒na tak─▒lan t├╝m nesneleri bellekte kalana kadar Nesne ayr─▒ca bellekte kal─▒r. Web uygulamam─▒zda, g├╝nl├╝kleri tek bir istekten ayr─▒ olarak ay─▒rmak i├žin bir istek kimli─čiyle ├ž─▒k─▒┼č ├ž─▒k─▒┼člar─▒n─▒ etiketlemek i├žin NDC kullan─▒yoruz. NDC etiketini bir i┼č par├žac─▒─č─▒yla ili┼čkilendiren kap, yan─▒t─▒ bir istekten d├Ând├╝r├╝rken de kald─▒r─▒r. Sorun, bir istek i┼členirken a┼ča─č─▒daki kod gibi bir alt i┼č par├žac─▒─č─▒ do─čdu─čunda meydana geldi:

 pubclic class RequestProcessor {
    private static final Logger logger = Logger.getLogger(RequestProcessor.class);
    public void doSomething()  {
        ....
        final List<String> hugeList = new ArrayList<String>(10000);
        new Thread() {
           public void run() {
               logger.info("Child thread spawned")
               for(String s:hugeList) {
                   ....
               }
           }
        }.start();
    }
}    
 

Bu y├╝zden bir NDC ba─člam─▒, do─čmu┼č olan sat─▒r i├ži iple ili┼čkilendirildi. Bu NDC ba─člam─▒ i├žin anahtar olan thread nesnesi, hugeList nesnesinin ├╝zerinde as─▒l─▒ oldu─ču sat─▒r i├ži dizisidir. Bu nedenle, i┼č par├žac─▒─č─▒ ne yapt─▒─č─▒n─▒ yapt─▒ktan sonra bile, hugeList'e yap─▒lan referans NDC ba─člam─▒nda Hastable taraf─▒ndan canl─▒ tutuldu, b├Âylece bir bellek s─▒z─▒nt─▒s─▒na neden oldu.


22







G├Âr├╝┼čme yapan ki┼či muhtemelen a┼ča─č─▒daki kod gibi dairesel bir referans ar─▒yordu (bu, tesad├╝fen yaln─▒zca art─▒k ge├žerli olmayan eski say─▒m JVM'lerinde yaln─▒zca bellek s─▒zd─▒r─▒yor). Ancak bu olduk├ža belirsiz bir soru, bu nedenle JVM bellek y├Ânetimi anlay─▒┼č─▒n─▒z─▒ g├Âstermek i├žin ├Ânemli bir f─▒rsat.

 class A {
    B bRef;
}

class B {
    A aRef;
}

public class Main {
    public static void main(String args[]) {
        A myA = new A();
        B myB = new B();
        myA.bRef = myB;
        myB.aRef = myA;
        myA=null;
        myB=null;
        /* at this point, there is no access to the myA and myB objects, */
        /* even though both objects still have active references. */
    } /* main */
}
 

Daha sonra, referans say─▒m─▒ ile yukar─▒daki kodun haf─▒zaya s─▒zaca─č─▒n─▒ a├ž─▒klayabilirsiniz. Fakat ├žo─ču modern JVM art─▒k referans say─▒m─▒ kullanm─▒yor, ├žo─ču bu hat─▒ralar─▒ toplayacak olan bir ├ž├Âp toplay─▒c─▒ kullan─▒yor.

Daha sonra, bunun gibi altta yatan bir yerel kayna─ča sahip bir Nesne olu┼čturmay─▒ a├ž─▒klayabilirsiniz:

 public class Main {
    public static void main(String args[]) {
        Socket s = new Socket(InetAddress.getByName("google.com"),80);
        s=null;
        /* at this point, because you didn't close the socket properly, */
        /* you have a leak of a native descriptor, which uses memory. */
    }
}
 

Daha sonra bunun teknik olarak bir bellek s─▒z─▒nt─▒s─▒ oldu─čunu a├ž─▒klayabilirsiniz, ancak s─▒z─▒nt─▒ya, JVM'deki Java kodunuz taraf─▒ndan serbest b─▒rak─▒lmayan temel yerel kaynaklar─▒ tahsis eden yerel kod neden olur.

G├╝n├╝n sonunda, modern bir JVM ile, JVM'nin fark─▒ndal─▒─č─▒n─▒n normal kapsam─▒ d─▒┼č─▒nda yerel bir kaynak tahsis eden bir miktar Java kodu yazman─▒z gerekir.


19







Statik bir Harita olu┼čturun ve ona sabit referanslar eklemeye devam edin. Bunlar asla GC'd olmayacak.

 public class Leaker {
    private static final Map<String, Object> CACHE = new HashMap<String, Object>();

    // Keep adding until failure.
    public static void addToCache(String key, Object value) { Leaker.CACHE.put(key, value); }
}
 

18







Herkes her zaman yerel kod yolunu unutur. ─░┼čte bir s─▒z─▒nt─▒ i├žin basit bir form├╝l:

  1. Yerel y├Ântemi bildir.
  2. Yerel y├Ântemde aray─▒n malloc . Arama free .
  3. Yerel y├Ântemi ├ža─č─▒r─▒n.

Unutmay─▒n, yerel koddaki bellek ay─▒rmalar─▒ JVM y─▒─č─▒n─▒ndan gelir.


17







Bu s─▒n─▒f─▒n finalize y├Ânteminde yeni bir s─▒n─▒f ├Ârne─či olu┼čturarak hareketli bir bellek s─▒z─▒nt─▒s─▒ olu┼čturabilirsiniz. Sonland─▒r─▒c─▒ birden fazla ├Ârnek olu┼čturursa bonus puan. ─░┼čte y─▒─č─▒n b├╝y├╝kl├╝─č├╝ne ba─čl─▒ olarak bir miktar birka├ž saniye ile birka├ž dakika aras─▒nda t├╝m y─▒─č─▒n─▒ s─▒zd─▒ran basit bir program:

 class Leakee {
    public void check() {
        if (depth > 2) {
            Leaker.done();
        }
    }
    private int depth;
    public Leakee(int d) {
        depth = d;
    }
    protected void finalize() {
        new Leakee(depth + 1).check();
        new Leakee(depth + 1).check();
    }
}

public class Leaker {
    private static boolean makeMore = true;
    public static void done() {
        makeMore = false;
    }
    public static void main(String[] args) throws InterruptedException {
        // make a bunch of them until the garbage collector gets active
        while (makeMore) {
            new Leakee(0).check();
        }
        // sit back and watch the finalizers chew through memory
        while (true) {
            Thread.sleep(1000);
            System.out.println("memory=" +
                    Runtime.getRuntime().freeMemory() + " / " +
                    Runtime.getRuntime().totalMemory());
        }
    }
}
 

16







Bunu hen├╝z kimsenin s├Âylemedi─čini sanm─▒yorum: finalize () y├Ântemini ge├žersiz k─▒larak finalize () y├Ânteminin bir yere g├Ânderilmesini sa─člayacak ┼čekilde bir nesneyi yeniden y├Ânlendirebilirsiniz. ├ç├Âp toplay─▒c─▒ nesneye yaln─▒zca bir kez ├ža─čr─▒lacakt─▒r, bundan sonra nesne asla imha edilmeyecektir.


15







Son zamanlarda daha ince bir kaynak s─▒z─▒nt─▒s─▒ ile kar┼č─▒la┼čt─▒m. Kaynaklar─▒ s─▒n─▒f y├╝kleyicinin getResourceAsStream ├╝zerinden a├žt─▒k ve girdi ak─▒┼č─▒ tan─▒t─▒c─▒lar─▒n─▒n kapat─▒lmad─▒─č─▒ ortaya ├ž─▒kt─▒.

Uhm, ne kadar aptal diyebilirsin.

Peki, bunu ilgin├ž yapan ┼čey ┼ču: bu yolla, JVM'nin y─▒─č─▒ndan ziyade, temel s├╝recin y─▒─č─▒n haf─▒zas─▒n─▒ s─▒zd─▒rabilirsiniz.

─░htiyac─▒n─▒z olan tek ┼čey i├žinde Java kodundan referans al─▒nacak bir dosya olan bir kavanoz dosyas─▒. Jar dosyas─▒ b├╝y├╝d├╝k├že, daha h─▒zl─▒ bellek ayr─▒l─▒r.

A┼ča─č─▒daki s─▒n─▒fla kolayca b├Âyle bir kavanoz yaratabilirsiniz:

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class BigJarCreator {
    public static void main(String[] args) throws IOException {
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File("big.jar")));
        zos.putNextEntry(new ZipEntry("resource.txt"));
        zos.write("not too much in here".getBytes());
        zos.closeEntry();
        zos.putNextEntry(new ZipEntry("largeFile.out"));
        for (int i=0 ; i<10000000 ; i++) {
            zos.write((int) (Math.round(Math.random()*100)+20));
        }
        zos.closeEntry();
        zos.close();
    }
}
 

Sadece BigJarCreator.java adl─▒ bir dosyaya yap─▒┼čt─▒r─▒n, derleyin ve komut sat─▒r─▒ndan ├žal─▒┼čt─▒r─▒n:

 javac BigJarCreator.java
java -cp . BigJarCreator
 

Ayr─▒ca, ge├žerli ├žal─▒┼čma dizininizde i├žinde iki dosya bulunan bir kavanoz ar┼čivi bulunur.

─░kinci bir s─▒n─▒f olu┼čtural─▒m:

 public class MemLeak {
    public static void main(String[] args) throws InterruptedException {
        int ITERATIONS=100000;
        for (int i=0 ; i<ITERATIONS ; i++) {
            MemLeak.class.getClassLoader().getResourceAsStream("resource.txt");
        }
        System.out.println("finished creation of streams, now waiting to be killed");

        Thread.sleep(Long.MAX_VALUE);
    }

}
 

Bu s─▒n─▒f temel olarak hi├žbir ┼čey yapmaz, ancak referans al─▒nmayan InputStream nesneleri olu┼čturur. Bu nesneler derhal toplanacak ├ž├Âplerdir ve bu nedenle y─▒─č─▒n boyutuna katk─▒da bulunmazlar. ├ľrne─čimiz i├žin mevcut bir kayna─č─▒ bir jar dosyas─▒ndan y├╝klemek ├Ânemlidir ve burada b├╝y├╝kl├╝─č├╝ ├Ânemlidir!

┼×├╝pheniz varsa, yukar─▒daki s─▒n─▒f─▒ derlemeye ve ba┼člatmaya ├žal─▒┼č─▒n, ancak d├╝zg├╝n bir y─▒─č─▒n boyutu (2 MB) se├žti─činizden emin olun:

 javac MemLeak.java
java -Xmx2m -classpath .:big.jar MemLeak
 

Burada bir OOM hatas─▒yla kar┼č─▒la┼čmazs─▒n─▒z, referanslar tutulmad─▒─č─▒ndan, yukar─▒daki ├Ârnekte ─░TERASYONLARI ne kadar b├╝y├╝k se├žerseniz se├žin uygulama ├žal─▒┼čmaya devam edecektir. ─░┼čleminizdeki bellek t├╝ketimi (├╝stte g├Âr├╝n├╝r (RES / RSS)) veya i┼člem gezgini), uygulama wait komutuna gelmedik├že artar. Yukar─▒daki kurulumda, yakla┼č─▒k 150 MB belle─če ayr─▒lacak.

Uygulaman─▒n g├╝venli bir ┼čekilde ├žal─▒┼čmas─▒n─▒ istiyorsan─▒z, giri┼č ak─▒┼č─▒n─▒ olu┼čturuldu─ču yerin hemen yan─▒nda kapat─▒n:

 MemLeak.class.getClassLoader().getResourceAsStream("resource.txt").close();
 

ve i┼čleminiz yineleme say─▒s─▒ndan ba─č─▒ms─▒z olarak 35 MB'─▒ a┼čmayacakt─▒r.

Olduk├ža basit ve ┼ča┼č─▒rt─▒c─▒.


15







Bir├žok insan─▒n ├Ânerdi─či gibi, Kaynak Ka├žaklar─▒'n─▒n JDBC ├Ârnekleri gibi sebep olmas─▒ olduk├ža kolayd─▒r. Ger├žek Bellek s─▒z─▒nt─▒lar─▒ biraz daha zor - ├Âzellikle JVM'nin k─▒r─▒k par├žalar─▒na g├╝venmiyorsan─▒z, bunu sizin i├žin ...

├çok b├╝y├╝k bir alan─▒ kaplayan ve daha sonra bunlara eri┼čemeyen nesneler olu┼čturma fikirleri de ger├žek bellek s─▒z─▒nt─▒s─▒ de─čildir. E─čer hi├žbir ┼čey eri┼čemezse, o zaman ├ž├Âp toplanacak ve e─čer bir ┼čey eri┼čebilecekse o zaman bu bir s─▒z─▒nt─▒ de─čil ...

Bir ┼čekilde kullan─▒lan ve hala yaparsa bilmiyorum - - ─░┼čin olsa yapaca─č─▒ ├╝├ž derin dairesel zincir sahip olmakt─▒r. A Nesnesinin, B Nesnesine bir referans─▒ oldu─ču gibi, B Nesnesi, C Nesnesine bir referansa sahiptir ve C Nesnesinin, A Nesnesine bir referans─▒ vard─▒r. GC, A <--> B'deki gibi iki derin zincirin oldu─čunu bilecek kadar zekiydi. - e─čer A ve B ba┼čka hi├žbir ┼čey taraf─▒ndan eri┼čilebilir de─čilse, ancak ├╝├ž yollu zincirle ba┼ča ├ž─▒kam─▒yorsa, g├╝venle toplanabilir ...


14







Haf─▒zan─▒n s─▒zaca─č─▒ bir├žok farkl─▒ durum var. Kar┼č─▒la┼čt─▒─č─▒m bir harita, a├ž─▒─ča ├ž─▒kmamas─▒ ve ba┼čka yerlerde kullan─▒lmamas─▒ gereken bir harita ortaya ├ž─▒kard─▒.

 public class ServiceFactory {

private Map<String, Service> services;

private static ServiceFactory singleton;

private ServiceFactory() {
    services = new HashMap<String, Service>();
}

public static synchronized ServiceFactory getDefault() {

    if (singleton == null) {
        singleton = new ServiceFactory();
    }
    return singleton;
}

public void addService(String name, Service serv) {
    services.put(name, serv);
}

public void removeService(String name) {
    services.remove(name);
}

public Service getService(String name, Service serv) {
    return services.get(name);
}

// the problematic api, which expose the map.
//and user can do quite a lot of thing from this api.
//for example, create service reference and forget to dispose or set it null
//in all this is a dangerous api, and should not expose 
public Map<String, Service> getAllServices() {
    return services;
}

}

// resource class is a heavy class
class Service {

}
 

11







─░plikler sonlan─▒ncaya kadar toplanmaz. ├ç├Âp toplaman─▒n k├Âkleri olarak g├Ârev yaparlar. Onlar, sadece onlar─▒ unutmak veya onlara referanslar─▒ silmekle geri al─▒nmayacak olan birka├ž nesneden biridir.

┼×unu d├╝┼č├╝n├╝n: ├çal─▒┼čan bir i┼č par├žac─▒─č─▒n─▒ sonland─▒rmak i├žin temel desen i┼č par├žac─▒─č─▒ taraf─▒ndan g├Âr├╝len baz─▒ ko┼čul de─či┼čkenini ayarlamakt─▒r. ─░plik de─či┼čkeni periyodik olarak kontrol edebilir ve bunu sonland─▒rmak i├žin bir sinyal olarak kullanabilir. De─či┼čken bildirilmezse volatile , de─či┼čkende yap─▒lan de─či┼čiklik i┼č par├žac─▒─č─▒ taraf─▒ndan g├Âr├╝lemeyebilir, bu nedenle sonland─▒rmay─▒ bilemez. Veya baz─▒ i┼č par├žac─▒klar─▒n─▒n payla┼č─▒lan bir nesneyi g├╝ncellemek isteyip istemedi─čini, ancak ├╝zerinde kilitlemeye ├žal─▒┼č─▒rken kilitlenmeyi hayal edin.

Yaln─▒zca bir avu├ž i┼č par├žac─▒─č─▒n─▒z varsa, bu hatalar muhtemelen a├ž─▒k olacakt─▒r ├ž├╝nk├╝ program─▒n─▒z d├╝zg├╝n ├žal─▒┼čmay─▒ b─▒rakacakt─▒r. Gerekti─činde daha fazla i┼č par├žac─▒─č─▒ olu┼čturan bir i┼č par├žac─▒─č─▒ havuzunuz varsa, kullan─▒lmayan / s─▒k─▒┼čm─▒┼č i┼č par├žac─▒klar─▒ fark edilmeyebilir ve s├╝resiz olarak birikerek bellek s─▒z─▒nt─▒s─▒na neden olabilir. ─░plikler uygulaman─▒zdaki di─čer verileri kullanmas─▒ muhtemeldir, bu nedenle do─črudan referans ald─▒klar─▒ herhangi bir ┼čeyin toplanmas─▒n─▒ da ├Ânler.

Oyuncak ├Ârne─či olarak:

 static void leakMe(final Object object) {
    new Thread() {
        public void run() {
            Object o = object;
            for (;;) {
                try {
                    sleep(Long.MAX_VALUE);
                } catch (InterruptedException e) {}
            }
        }
    }.start();
}
 

├ça─čr─▒ System.gc() sizin gibi t├╝m, ama ge├žirilen nesne leakMe asla ├Âlmeyecek.

(* D├╝zenlenmi┼č *)


11







Ge├žerli bir ├Ârnek, ThreadLocal de─či┼čkenlerini, i┼č par├žac─▒klar─▒n─▒n topland─▒─č─▒ bir ortamda kullan─▒yor olabilece─čini d├╝┼č├╝n├╝yorum.

├ľrne─čin, Servlets'teki ThreadLocal de─či┼čkenlerini kullanarak, di─čer web bile┼čenleri ile ileti┼čim kurmak, i┼č par├žac─▒─č─▒ taraf─▒ndan konteyner taraf─▒ndan olu┼čturulmak ve bo┼čta kalanlar─▒ bir havuzda tutmak. ThreadLocal de─či┼čkenleri, e─čer do─čru ┼čekilde temizlenmemi┼čse, muhtemelen ayn─▒ web bile┼čeni de─čerlerinin ├╝zerine yazana kadar orada ya┼čayacakt─▒r.

Tabii ki, bir kez tan─▒mland─▒ktan sonra problem kolayca ├ž├Âz├╝lebilir.


10







G├Âr├╝┼čme yapan ki┼či dairesel bir referans ├ž├Âz├╝m├╝ ar─▒yor olabilir:

     public static void main(String[] args) {
        while (true) {
            Element first = new Element();
            first.next = new Element();
            first.next.next = first;
        }
    }
 

Bu, referans sayma ├ž├Âp toplay─▒c─▒lar─▒ ile klasik bir sorundur. Daha sonra, JVM'lerin bu s─▒n─▒rlamaya sahip olmayan ├žok daha karma┼č─▒k bir algoritma kulland─▒klar─▒n─▒ kibarca a├ž─▒klars─▒n─▒z.

-We Tarle


10



─░lgili yay─▒nlar


Chrome ile JavaScript bellek s─▒z─▒nt─▒s─▒ bulma

Java bellek s─▒z─▒nt─▒s─▒ nas─▒l bulunur

.NET'te bir MemoryStream kapal─▒ de─čilse, bir bellek s─▒z─▒nt─▒s─▒ olu┼čturulmu┼č mu?

Scalaz 7 zipWithIndex / group enumeratees ile bellek s─▒z─▒nt─▒lar─▒n─▒ ├Ânleme

Java'da bir bellek s─▒z─▒nt─▒s─▒ / ├ž├Âp toplama sorununu izleme

Go, JavaÔÇÖn─▒n oldu─ču ayn─▒ ince bellek s─▒z─▒nt─▒lar─▒na maruz kal─▒yor mu?

bellek s─▒z─▒nt─▒s─▒ nedir? neden java.lang.ref.Finalizer bu kadar haf─▒zay─▒ yiyor?

Ka├žaklar cihaz─▒ g├Âsterilmedi─činde bellek s─▒z─▒nt─▒lar─▒ nas─▒l debug edilir?

Java Standard API'sinde bellek s─▒z─▒nt─▒s─▒ tuzaklar─▒

Node.js ile uzun ba─člant─▒lar, bellek kullan─▒m─▒n─▒ nas─▒l azaltabilir ve bellek s─▒z─▒nt─▒s─▒n─▒ nas─▒l ├Ânleyebilirim? Ayr─▒ca V8 ve webkit-devtools ile ilgili

Etiketle ilgili di─čer sorular [java]


Olay k├Âp├╝rme ve yakalama nedir?

Bir g├╝nden bir g├╝n nas─▒l ├ž─▒kar─▒l─▒r?

Bir Listeyi Java'daki Bir K├╝meye D├Ân├╝┼čt├╝rmenin En Kolay Yolu

Eclipse / Java kodu tamamlama ├žal─▒┼čm─▒yor

Printf, dizgede yeni bir sat─▒r olmad─▒k├ža ├ža─čr─▒dan sonra neden d├╝zle┼čmiyor?

Birden fazla ├Â─če i├žin jQuery ayn─▒ t─▒klama olay─▒

EditText i├žin ilk harf b├╝y├╝k harf

─░OS a─č uygulamalar─▒ olu┼čturmak i├žin en iyi mimari yakla┼č─▒mlar (REST m├╝┼čterileri)

Mockito: Y├Ânteme g├Âz atmaya ├žal─▒┼čmak orijinal y├Ântemi ├ža─č─▒r─▒yor

AngularJS kullanarak sayfan─▒n tamam─▒ nas─▒l yeniden y├╝klenir veya yeniden olu┼čturulur