2016-03-10 6 views
15

में मेमोरी लीक के लिए निगरानी वर्षों के लिए, हम +UseParallelOldGC का उपयोग कर मामूली ढेर आकारों के साथ जावा सेवाओं चल रहा है। अब, हम एक बड़े ढेर और जी 1 कलेक्टर का उपयोग कर एक नई सेवा शुरू करना शुरू कर रहे हैं। यह बहुत अच्छी तरह से जा रहा है।जावा G1: उत्पादन

+UseParallelOldGC का उपयोग करने वाली हमारी सेवाओं के लिए, हम संग्रहण के बाद पुराने पीढ़ी के आकार को देखकर और थ्रेसहोल्ड पर सतर्क करके स्मृति रिसाव की निगरानी करते हैं। यह काफी अच्छी तरह से काम करता है, और वास्तव में केवल दो हफ्ते पहले हमारे बेकन को बचाया।

  • ManagementFactory.getMemoryPoolMXBeans()
  • नाम "Old Gen"
  • में समाप्त होने के साथ MemoryPoolMXBean परिणाम के लिए खोज getCollectionUsage().getUsed() तुलना करें (यदि उपलब्ध हो) getMax()
साथ:

विशेष रूप से, +UseParallelOldGC के लिए, हम निम्न कार्य करें

दुर्भाग्यवश, ऐसा लगता है कि जी 1 में अब 012 की अवधारणा नहीं है।

मूल रूप से, हालांकि, हम पिछले मिश्रित संग्रह यह एक मिश्रित चक्र, या कुछ इसी तरह में करना चुनता निम्नलिखित G1 ढेर आकार की निगरानी करना चाहते हैं।

उदाहरण के लिए, वी एम के बाहर मैं एक awk स्क्रिप्ट केवल पाया गया कि पिछले '(mixed)' था कि एक '(young)' द्वारा पीछा किया और देखो क्या अंतिम ढेर आकार था के साथ खुशी होगी (जैसे, '1540.0M' 'Heap: 3694.5M(9216.0M)->1540.0M(9216.0M)')

वहाँ किसी भी है जावा वीएम के अंदर ऐसा करने का तरीका?

+0

इस इसी तरह की जानकारी प्रदान करना चाहिए (शायद संग्रह आवृत्ति को कई संग्रहों से सभा सांख्यिकी, आदि के आधार पर) का पता लगाने में और अधिक परिष्कृत रणनीति खोजने की जरूरत है: http://stackoverflow.com/a/ 32509813/1362755 – the8472

उत्तर

2

हाँ, JVM यदि आपके पास पर्याप्त उपकरण G1 के लिए इस तरह की जानकारी को पुनः प्राप्त करने देता है। उदाहरण के लिए, आप इस वर्ग कि कचरा संग्रह के बारे में सभी विवरण प्रिंट (बस MemoryUtil.startGCMonitor() कहते हैं) की तरह कुछ इस्तेमाल कर सकते हैं:

public class MemoryUtil { 

    private static final Set<String> heapRegions; 

    static { 
     heapRegions = ManagementFactory.getMemoryPoolMXBeans().stream() 
       .filter(b -> b.getType() == MemoryType.HEAP) 
       .map(MemoryPoolMXBean::getName) 
       .collect(Collectors.toSet()); 
    } 

    private static NotificationListener gcHandler = (notification, handback) -> { 
     if (notification.getType().equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { 
      GarbageCollectionNotificationInfo gcInfo = GarbageCollectionNotificationInfo.from((CompositeData) notification.getUserData()); 
      Map<String, MemoryUsage> memBefore = gcInfo.getGcInfo().getMemoryUsageBeforeGc(); 
      Map<String, MemoryUsage> memAfter = gcInfo.getGcInfo().getMemoryUsageAfterGc(); 
      StringBuilder sb = new StringBuilder(250); 
      sb.append("[").append(gcInfo.getGcAction()).append("/").append(gcInfo.getGcCause()) 
        .append("/").append(gcInfo.getGcName()).append("/("); 
      appendMemUsage(sb, memBefore); 
      sb.append(") -> ("); 
      appendMemUsage(sb, memAfter); 
      sb.append("), ").append(gcInfo.getGcInfo().getDuration()).append(" ms]"); 
      System.out.println(sb.toString()); 
     } 
    }; 

    public static void startGCMonitor() { 
     for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) { 
      ((NotificationEmitter) mBean).addNotificationListener(gcHandler, null, null); 
     } 
    } 

    public static void stopGCMonitor() { 
     for(GarbageCollectorMXBean mBean: ManagementFactory.getGarbageCollectorMXBeans()) { 
      try { 
       ((NotificationEmitter) mBean).removeNotificationListener(gcHandler); 
      } catch(ListenerNotFoundException e) { 
       // Do nothing 
      } 
     } 
    } 

    private static void appendMemUsage(StringBuilder sb, Map<String, MemoryUsage> memUsage) { 
     memUsage.entrySet().forEach((entry) -> { 
      if (heapRegions.contains(entry.getKey())) { 
       sb.append(entry.getKey()).append(" used=").append(entry.getValue().getUsed() >> 10).append("K; "); 
      } 
     }); 
    } 
} 

इस कोड में, gcInfo.getGcAction() आप प्रमुख/मिश्रित लोगों से नाबालिग संग्रह अलग करने के लिए पर्याप्त जानकारी देता है।

लेकिन वहाँ G1 करने के लिए अपने दृष्टिकोण (एक सीमा के साथ) का उपयोग करने के लिए एक महत्वपूर्ण चेतावनी है। जी 1 में एक मिश्रित संग्रह आमतौर पर केवल कई पुराने जीन क्षेत्रों को प्रभावित करता है - जीसी को कम रखने के लिए पर्याप्त मात्रा में स्मृति मुक्त करने के लिए पर्याप्त नहीं है लेकिन बहुत अधिक नहीं है। तो, जी 1 में मिश्रित संग्रह के बाद आप यह सुनिश्चित नहीं कर सकते कि आपका कचरा खत्म हो गया है। नतीजतन, आप मेमोरी लीक

संबंधित मुद्दे