怎么样写出带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语法可以用于自动关闭资源
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】博客园2025新款「AI繁忙」系列T恤上架,前往周边小店选购
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步