怎么樣寫出帶Bug的代碼
1、創建class時不沒有重寫hashCode()和equals()方法,輕則創建的對象比較時無法區分,重則將大量對象存儲至map時導致內存泄漏。
解決方法:根據業務需要重寫equals()方法和hashCode()方法。
2、內部類引用外部類
2.1、非靜態的內部類默認會持有外部類,盡管代碼上不再使用外部類,所以如果有地方引用了這個非靜態內部類,會導致外部類也被引用,垃圾回收時無法回收這個外部類。
舉例
public class Outer{ private byte[] bytes = new byte[1024]; //外部類持有數據 private String name = "Bug"; class Inner{ private String name; public Inner() { this.name = Outer.this.name; } } public static void main(String[] args) throws IOException, InterruptedException { int count = 0; ArrayList<Inner> inners = new ArrayList<>(); while (true){ if(count++ % 100 == 0){ Thread.sleep(10); } inners.add(new Outer().new Inner()); } } }
解決方法:使用靜態內部類
public class FixOuter { private byte[] bytes = new byte[1024 * 1024]; //外部類持有數據 private static String name = "Bug"; static class Inner{ private String name; public Inner() { this.name = FixOuter.name; } } public static void main(String[] args) throws IOException, InterruptedException { int count = 0; ArrayList<Inner> inners = new ArrayList<>(); while (true){ if(count++ % 100 == 0){ Thread.sleep(10); } inners.add(new Inner()); } } }
2.2、匿名內部類對象如果在非靜態方法中被創建,會持有調用者對象,垃圾回收時無法回收調用者。
舉例
public class Outer { private byte[] bytes = new byte[1024]; public List<String> newList() { List<String> list = new ArrayList<String>() {{ add("1"); add("2"); }}; return list; } public static void main(String[] args) throws IOException { int count = 0; ArrayList<Object> objects = new ArrayList<>(); while (true){ System.out.println(++count); objects.add(new Outer().newList()); } } }
解決方法:使用靜態方法
public class FixOuter { private byte[] bytes = new byte[1024]; public static List<String> newList() { List<String> list = new ArrayList<String>() {{ add("1"); add("2"); }}; return list; } public static void main(String[] args) throws IOException { int count = 0; ArrayList<Object> objects = new ArrayList<>(); while (true){ System.out.println(++count); objects.add(newList()); } } }
3、ThreadLocal使用不當
3.1、ThreadLocal變量會與線程綁定,如果線程長時間存在(例如線程池中的線程),而ThreadLocal變量沒有被及時移除,可能會導致內存泄漏。
解決方法在使用完ThreadLocal變量后,調用remove()方法移除變量。
3.2、ThreadLocal本身是線程安全的,但需要注意在使用ThreadLocal變量時,不要在多個線程中共享同一個ThreadLocal實例。
解決方法每個線程使用自己的ThreadLocal實例,或者使用InheritableThreadLocal來實現線程間的數據傳遞
4、IO或者網絡資源沒有正確關閉
解決方案:在finally塊中關閉不再使用的資源;從 Java 7 開始,使用try-with-resources語法可以用于自動關閉資源

浙公網安備 33010602011771號