Java常见异常详解及解决方案(七)

 Java异常处理是编程中的重要部分,下面我将分类讲解常见的异常类型,通过具体示例说明其产生原因,并提供相应的解决策略。

61. DirectoryIteratorException (目录迭代异常)

示例

try {
    Files.walk(Paths.get(".")).forEach(path -> {
        // 访问无权限目录
    });
} catch(DirectoryIteratorException e) {
    // 目录迭代过程中出错
}

原因:目录遍历过程中发生IO错误

解决策略

  • 处理单个文件错误

  • 跳过无权限目录

  • 使用安全遍历方法

// 解决方案示例
try {
    Files.walk(Paths.get(".")).forEach(path -> {
        try {
            // 处理文件
        } catch(IOException e) {
            logger.warn("跳过文件: " + path, e);
        }
    });
} catch(IOException e) {
    logger.error("遍历失败", e);
}

62. FileSystemLoopException (文件系统循环异常)

示例

try {
    Files.walk(Paths.get("."), FileVisitOption.FOLLOW_LINKS)
        .forEach(path -> {
            // 遇到符号链接循环
        });
} catch(FileSystemLoopException e) {
    // 检测到符号链接循环
}

原因:符号链接形成循环引用

解决策略

  • 限制遍历深度

  • 检测循环链接

  • 不使用FOLLOW_LINKS选项

// 解决方案示例
Files.walkFileTree(startPath, new SimpleFileVisitor() {
    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        if(/* 检测循环 */) {
            return FileVisitResult.SKIP_SUBTREE;
        }
        return FileVisitResult.CONTINUE;
    }
});

63. ProviderMismatchException (提供者不匹配异常)

示例

Path path1 = Paths.get("file1");
Path path2 = FileSystems.getFileSystem(URI.create("jar:file:/test.jar"))
    .getPath("file2");
try {
    path1.resolve(path2); // 不同文件系统提供者
} catch(ProviderMismatchException e) {
    // 路径来自不同提供者
}

原因:跨不同文件系统提供者操作路径

解决策略

  • 统一文件系统提供者

  • 转换路径

  • 使用中间操作

// 解决方案示例
Path resolved = path1.resolve(path2.toString());

64. SecurityException (安全异常)

示例

try {
    System.setSecurityManager(new SecurityManager());
    System.exit(0); // 抛出SecurityException
} catch(SecurityException e) {
    // 安全策略禁止操作
}

原因:违反安全策略的操作

解决策略

  • 检查安全权限

  • 使用特权操作

  • 请求必要权限

    // 解决方案示例
    AccessController.doPrivileged((PrivilegedAction) () -> {
        System.setProperty("key", "value");
        return null;
    });

    65. DOMException (DOM异常)

    示例

    try {
        Document doc = DocumentBuilderFactory.newInstance()
            .newDocumentBuilder().newDocument();
        doc.createElement("invalid name"); // 无效元素名
    } catch(DOMException e) {
        // DOM操作错误
    }

    原因:XML DOM操作错误

    解决策略

  • 验证DOM操作参数

  • 使用合规XML名称

  • 处理命名空间

    // 解决方案示例
    public static Element safeCreateElement(Document doc, String name) {
        try {
            return doc.createElement(name);
        } catch(DOMException e) {
            return doc.createElement("default");
        }
    }

    66. JMXException (JMX管理异常)

    示例

    try {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        ObjectName name = new ObjectName("com.example:type=Test");
        mbs.registerMBean(new Test(), name); // 重复注册
    } catch(JMXException e) {
        // JMX操作失败
    }

    原因:JMX管理操作失败(如MBean注册/注销问题)

    解决策略

  • 检查MBean命名唯一性

  • 验证MBean接口合规性

  • 使用JMXConnectorServer处理远程访问

    // 解决方案示例
    public static void registerMBean(Object mbean, String domain, String type) {
        try {
            ObjectName name = new ObjectName(domain + ":type=" + type);
            if(!mbs.isRegistered(name)) {
                mbs.registerMBean(mbean, name);
            }
        } catch(JMXException | MalformedObjectNameException e) {
            logger.error("MBean注册失败", e);
        }
    }

    67. MarshalException (编组异常)

    示例

    try {
        JAXBContext context = JAXBContext.newInstance(User.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.marshal(new User(), new File("user.xml"));
    } catch(MarshalException e) {
        // XML编组失败
    }

    原因:对象到XML的编组过程失败

    解决策略

  • 验证对象注解配置

  • 检查XML适配器

  • 处理循环引用

    // 解决方案示例
    @XmlRootElement
    class User {
        @XmlTransient // 避免循环引用
        public Department department;
    }

    68. UnmarshalException (解组异常)

    示例

    try {
        JAXBContext context = JAXBContext.newInstance(User.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        User user = (User) unmarshaller.unmarshal(new File("invalid.xml"));
    } catch(UnmarshalException e) {
        // XML解组失败
    }

    原因:XML到对象的解组过程失败

    解决策略

  • 验证XML结构符合XSD

  • 使用Schema验证

  • 处理日期/数字格式

    // 解决方案示例
    SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = sf.newSchema(new File("schema.xsd"));
    unmarshaller.setSchema(schema);

    69. PrintException (打印异常)

    示例

    DocFlavor flavor = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
    PrintService[] services = PrintServiceLookup.lookupPrintServices(flavor, null);
    try {
        services[0].createPrintJob().print(new SimpleDoc(new Printable(){...}, flavor, null));
    } catch(PrintException e) {
        // 打印服务错误
    }

    原因:打印系统操作失败

    解决策略

  • 检查打印服务状态

  • 验证文档格式

  • 处理用户取消操作

    // 解决方案示例
    public static boolean printDocument(Printable printable) {
        PrintService service = PrintServiceLookup.lookupDefaultPrintService();
        if(service != null) {
            try {
                DocPrintJob job = service.createPrintJob();
                job.addPrintJobListener(new PrintJobAdapter() {
                    public void printJobFailed(PrintJobEvent pje) {
                        logger.error("打印失败");
                    }
                });
                job.print(new SimpleDoc(printable, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null));
                return true;
            } catch(PrintException e) {
                logger.error("打印错误", e);
            }
        }
        return false;
    }

    70. FontFormatException (字体格式异常)

    示例

    try {
        Font font = Font.createFont(Font.TRUETYPE_FONT, new File("corrupted.ttf"));
    } catch(FontFormatException e) {
        // 字体文件损坏
    }

    原因:字体文件格式无效或损坏

    解决策略

  • 验证字体文件完整性

  • 使用系统备用字体

  • 提供字体加载重试机制

    // 解决方案示例
    public static Font loadFont(File fontFile) {
        try {
            return Font.createFont(Font.TRUETYPE_FONT, fontFile);
        } catch(FontFormatException | IOException e) {
            return new Font("Serif", Font.PLAIN, 12); // 返回系统默认字体
        }
    }

  • 异常处理高级模式

  • 异常转换框架

    public interface ExceptionTranslator {
        RuntimeException translate(Exception e);
    }
    
    public class JdbcExceptionTranslator implements ExceptionTranslator {
        public RuntimeException translate(Exception e) {
            if(e instanceof SQLException) {
                return new DataAccessException("数据库错误", e);
            }
            return new SystemException(e);
        }
    }

  • 错误上下文收集

    public class ErrorContext {
        private static ThreadLocal> context = 
            ThreadLocal.withInitial(HashMap::new);
        
        public static void put(String key, Object value) {
            context.get().put(key, value);
        }
        
        public static Map getContext() {
            return Collections.unmodifiableMap(context.get());
        }
    }
    
    // 使用示例
    try {
        ErrorContext.put("userId", currentUser);
        // 业务逻辑
    } catch(Exception e) {
        logger.error("操作失败,上下文: {}", ErrorContext.getContext(), e);
    }

    断路器模式

    public class CircuitBreaker {
        private final int failureThreshold;
        private final long timeout;
        private int failures;
        private long lastFailureTime;
        
        public  T execute(Supplier supplier) throws CircuitBreakerOpenException {
            if(System.currentTimeMillis() - lastFailureTime < timeout 
                && failures >= failureThreshold) {
                throw new CircuitBreakerOpenException("断路器已打开");
            }
            
            try {
                T result = supplier.get();
                reset();
                return result;
            } catch(Exception e) {
                recordFailure();
                throw e;
            }
        }
        
        private void recordFailure() {
            failures++;
            lastFailureTime = System.currentTimeMillis();
        }
        
        private void reset() {
            failures = 0;
        }
    }

  • 异步异常处理

    CompletableFuture.supplyAsync(() -> {
        // 可能失败的操作
        return fetchData();
    })
    .handle((result, ex) -> {
        if(ex != null) {
            logger.error("异步操作失败", ex);
            return fallbackData();
        }
        return result;
    })
    .thenAccept(this::processResult);

你可能感兴趣的:(java,开发语言)