content: package com.alphabugx.jar;
  
  import com.alphabugx.config.AppConfig;
  import com.alphabugx.security.SecurityManager;
  import com.alphabugx.util.ProgressReporter;
  import com.alphabugx.util.EncodingHelper;
  
  import java.io.*;
  import java.nio.file.*;
  import java.util.*;
  import java.util.concurrent.*;
  import java.util.concurrent.atomic.AtomicInteger;
  import java.util.jar.JarEntry;
  import java.util.jar.JarFile;
  import java.util.jar.JarOutputStream;
  import java.util.zip.ZipEntry;
  
  /**
   * Jar文件处理器
   * 实现Jar文件的解压、反编译、重编译和重打包功能
   */
  public class JarProcessor {
      private AppConfig config;
      private File workDir;
      private File jarFile;
      private File extractDir;
      private File sourceDir;
      private ProgressCallback progressCallback;
      private ProgressReporter progress;
      
      /**
       * 进度回调接口
       */
      public interface ProgressCallback {
          void updateProgress(String step, double progress, String message);
      }
      
      public JarProcessor() {
          this.config = AppConfig.getInstance();
          this.progress = ProgressReporter.getInstance();
      }
      
      /**
       * 设置进度回调
       */
      public void setProgressCallback(ProgressCallback callback) {
          this.progressCallback = callback;
      }
      
      /**
       * 通知进度更新
       */
      private void notifyProgress(String step, double progress, String message) {
          if (progressCallback != null) {
              progressCallback.updateProgress(step, progress, message);
          }
          System.out.println("[" + step + " " + String.format("%.1f", progress) + "%] " + message);
      }
      
      /**
       * 初始化工作目录
       */
      public void initWorkspace(File jarFile) throws IOException {
          this.jarFile = jarFile;
          
          // 根据操作系统创建临时目录
          String tempBasePath;
          String osName = System.getProperty("os.name").toLowerCase();
          
          if (osName.contains("win")) {
              // Windows: C:\Windows\Temp\jawd\
              tempBasePath = System.getenv("TEMP");
              if (tempBasePath == null) {
                  tempBasePath = "C:\\Windows\\Temp";
              }
              tempBasePath = tempBasePath + File.separator + "jawd";
          } else {
              // Linux/macOS: /tmp/jawd/
              tempBasePath = "/tmp/jawd";
          }
          
          // 创建基础临时目录
          File jawdTempDir = new File(tempBasePath);
          if (!jawdTempDir.exists() && !jawdTempDir.mkdirs()) {
              throw new IOException("无法创建JAWD临时目录: " + jawdTempDir.getAbsolutePath());
          }
          
          // 为当前Jar文件创建专用工作目录 - 使用短后缀减少路径长度
          String jarBaseName = jarFile.getName().replaceAll("\\.[^.]+$", ""); // 移除扩展名
          
          // 使用6位时间戳后缀（毫秒的最后6位）
          String timestamp = String.valueOf(System.currentTimeMillis() % 1000000);
          
          // 添加6位随机数确保唯一性，防止同一时刻多次打开同一jar文件冲突
          String randomSuffix = String.format("%06d", (int)(Math.random() * 1000000));
          
          this.workDir = new File(jawdTempDir, jarBaseName + "_" + timestamp + "_" + randomSuffix);
          this.extractDir = new File(workDir, "extracted");
          this.sourceDir = new File(workDir, "src/main/java");
          
          // 创建目录结构
          if (!sourceDir.mkdirs()) {
              throw new IOException("无法创建工作目录: " + sourceDir.getAbsolutePath());
          }
          
          System.out.println("工作目录初始化完成: " + workDir.getAbsolutePath());
      }
      
      /**
       * 解压Jar文件
       */
      public void extractJar() throws IOException {
          progress.startMainTask("解压Jar文件", 100);
          progress.updateMainProgress(0, "初始化解压 " + jarFile.getName());
          
          try (JarFile jar = new JarFile(jarFile)) {
              // 先统计总文件数
              long totalEntries = jar.stream().count();
              progress.reportInfo("发现 " + totalEntries + " 个文件/目录");
              
              final AtomicInteger processedEntries = new AtomicInteger(0);
              
              jar.stream().forEach(entry -> {
                  try {
                      int current = processedEntries.incrementAndGet();
                      int progressPercent = (int) ((current * 100.0) / totalEntries);
                      
                      String fileName = entry.getName();
                      if (fileName.length() > 50) {
                          fileName = "..." + fileName.substring(fileName.length() - 47);
                      }
                      
                      progress.updateMainProgress(progressPercent, "解压: " + fileName);
                      
                      File targetFile = new File(extractDir, entry.getName());
                      
                      if (entry.isDirectory()) {
                          targetFile.mkdirs();
                          progress.reportInfo("创建目录: " + entry.getName());
                      } else {
                          // 确保父目录存在
                          targetFile.getParentFile().mkdirs();
                          
                          // 复制文件
                          try (InputStream is = jar.getInputStream(entry);
                               FileOutputStream fos = new FileOutputStream(targetFile)) {
                              byte[] buffer = new byte[8192];
                              int length;
                              long totalBytes = 0;
                              while ((length = is.read(buffer)) > 0) {
                                  fos.write(buffer, 0, length);
                                  totalBytes += length;
                              }
                              
                              if (totalBytes > 1024 * 1024) { // 大于1MB的文件记录
                                  progress.reportInfo("解压大文件: " + entry.getName() + " (" + formatFileSize(totalBytes) + ")");
                              }
                          }
                      }
                  } catch (IOException e) {
                      progress.reportError("解压文件失败: " + entry.getName(), e);
                      throw new RuntimeException("解压文件失败: " + entry.getName(), e);
                  }
              });
          }
          
          progress.updateMainProgress(100, "解压完成");
          progress.completeMainTask();
      }
      
      /**
       * 复制Class文件到源码目录
       */
      public void copyClassFiles() throws IOException {
          System.out.println("复制Class文件到源码目录");
          
          // 查找BOOT-INF/classes目录或直接的class文件
          File classesDir = new File(extractDir, "BOOT-INF/classes");
          if (!classesDir.exists()) {
              classesDir = extractDir; // 普通Jar文件
          }
          
          if (classesDir.exists()) {
              copyDirectory(classesDir, sourceDir);
              System.out.println("Class文件复制完成");
          } else {
              throw new IOException("未找到Class文件目录");
          }
      }
      
      /**
       * 使用CFR反编译Class文件 - 多线程优化版本
       */
      public void decompileClasses() throws IOException, InterruptedException {
          progress.startMainTask("反编译Class文件", 100);
          progress.updateMainProgress(0, "初始化反编译环境");
          
          String cfrPath = config.getCfrPath();
          String javaExe = config.getJavaExecutable();
          
          // 检查CFR工具是否存在
          if (!new File(cfrPath).exists()) {
              progress.reportError("CFR工具不存在: " + cfrPath, null);
              throw new IOException("CFR工具不存在: " + cfrPath);
          }
          
          progress.updateMainProgress(10, "查找Class文件");
          
          // 查找所有class文件并反编译
          List<File> classFiles = findClassFiles(sourceDir);
          progress.reportInfo("找到 " + classFiles.size() + " 个Class文件需要反编译");
          
          if (classFiles.isEmpty()) {
              progress.updateMainProgress(100, "没有找到Class文件");
              progress.completeMainTask();
              return;
          }
          
          // 使用多线程反编译，线程数为CPU核心数，最多8个线程
          int threadCount = Math.min(Math.max(2, Runtime.getRuntime().availableProcessors()), 8);
          progress.reportInfo("使用 " + threadCount + " 个线程进行并行反编译");
          progress.updateMainProgress(15, "启动多线程反编译");
          
          ExecutorService executor = Executors.newFixedThreadPool(threadCount);
          AtomicInteger successCount = new AtomicInteger(0);
          AtomicInteger failureCount = new AtomicInteger(0);
          AtomicInteger processedCount = new AtomicInteger(0);
          
          // 提交所有反编译任务
          List<Future<Void>> futures = new ArrayList<>();
          for (File classFile : classFiles) {
              Future<Void> future = executor.submit(() -> {
                  try {
                      int current = processedCount.incrementAndGet();
                      int progressPercent = 15 + (int) ((current * 80.0) / classFiles.size()); // 15-95%
                      
                      String fileName = classFile.getName();
                      if (fileName.length() > 40) {
                          fileName = "..." + fileName.substring(fileName.length() - 37);
                      }
                      
                      // 详细进度报告
                      progress.reportFileProgress(fileName, current, classFiles.size(), "反编译");
                      progress.updateMainProgress(progressPercent, "反编译: " + fileName);
                      
                      // 通知进度更新（保持原有回调）
                      double callbackProgress = 30.0 + (current * 40.0 / classFiles.size()); // 30%-70%的进度区间
                      notifyProgress("反编译", callbackProgress, "反编译: " + classFile.getName() + " (" + current + "/" + classFiles.size() + ")");
                      
                      decompileClassFile(classFile, javaExe, cfrPath);
                      successCount.incrementAndGet();
                      
                      // 每50个文件报告一次统计
                      if (current % 50 == 0 || current == classFiles.size()) {
                          progress.reportInfo("反编译统计: 成功 " + successCount.get() + ", 失败 " + failureCount.get() + 
                                           " (总进度: " + current + "/" + classFiles.size() + ")");
                      }
                      
                  } catch (Exception e) {
                      progress.reportError("反编译失败: " + classFile.getName(), e);
                      failureCount.incrementAndGet();
                  }
                  return null;
              });
              futures.add(future);
          }
          
          // 等待所有任务完成
          for (Future<Void> future : futures) {
              try {
                  future.get(); // 等待单个任务完成
              } catch (ExecutionException e) {
                  System.err.println("反编译任务执行异常: " + e.getCause().getMessage());
              }
          }
          
          // 关闭线程池
          executor.shutdown();
          if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
              executor.shutdownNow();
          }
          
          progress.updateMainProgress(100, "反编译完成");
          progress.reportInfo("反编译最终统计: 成功 " + successCount.get() + ", 失败 " + failureCount.get());
          progress.completeMainTask();
          
          if (successCount.get() == 0) {
              progress.reportError("所有Class文件反编译都失败了，请检查CFR工具配置", null);
              throw new IOException("所有Class文件反编译都失败了，请检查CFR工具配置");
          }
      }
      
      /**
       * 反编译单个Class文件
       */
      private void decompileClassFile(File classFile, String javaExe, String cfrPath) 
              throws IOException, InterruptedException {
          
          String classDir = classFile.getParent();
          String className = classFile.getName().replace(".class", "");
          File javaFile = new File(classDir, className + ".java");
          
          // 构建CFR命令 - 使用更好的参数减少变量名混乱
          ProcessBuilder pb = new ProcessBuilder(
              javaExe, "-jar", cfrPath, 
              "--silent", "true",           // 减少冗余输出
              "--renamedupmembers", "false", // 不重命名重复成员
              "--renameillegalidents", "false", // 不重命名非法标识符
              "--renamesmallmembers", "0",   // 不重命名短变量名
              "--lenient", "true",          // 宽松模式，提高成功率
              "--recover", "true",          // 尝试恢复错误的字节码
              "--allowcorrecting", "true",  // 允许纠正
              classFile.getAbsolutePath()
          );
          pb.directory(new File("."));
          
          Process process = pb.start();
          
          // 读取输出并写入Java文件，同时清理CFR生成的注释
          try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
               FileWriter writer = new FileWriter(javaFile)) {
              
              String line;
              boolean skipCfrComment = true;
              boolean foundPackageOrImport = false;
              
              while ((line = reader.readLine()) != null) {
                  String trimmedLine = line.trim();
                  
                  // 跳过CFR生成的注释头
                  if (skipCfrComment) {
                      // 如果遇到package、import或class声明，停止跳过
                      if (trimmedLine.startsWith("package ") || 
                          trimmedLine.startsWith("import ") || 
                          trimmedLine.startsWith("public class ") ||
                          trimmedLine.startsWith("class ") ||
                          trimmedLine.startsWith("public interface ") ||
                          trimmedLine.startsWith("interface ") ||
                          trimmedLine.startsWith("@")) {
                          skipCfrComment = false;
                          foundPackageOrImport = true;
                          writer.write(line + System.lineSeparator());
                      }
                      // 跳过注释行、空行和CFR特殊标记
                      else if (trimmedLine.startsWith("/*") || 
                               trimmedLine.startsWith("*") || 
                               trimmedLine.startsWith("*/") || 
                               trimmedLine.isEmpty() ||
                               trimmedLine.startsWith("//")) {
                          // 跳过这些行
                          continue;
                      }
                      // 如果遇到其他内容，也停止跳过
                      else {
                          skipCfrComment = false;
                          writer.write(line + System.lineSeparator());
                      }
                  } else {
                      // 正常写入剩余内容
                      writer.write(line + System.lineSeparator());
                  }
              }
          }
          
          int exitCode = process.waitFor();
          if (exitCode != 0) {
              // 读取错误信息
              try (BufferedReader errorReader = new BufferedReader(
                      new InputStreamReader(process.getErrorStream()))) {
                  String errorLine;
                  StringBuilder errorMsg = new StringBuilder();
                  while ((errorLine = errorReader.readLine()) != null) {
                      errorMsg.append(errorLine).append("\n");
                  }
                  throw new RuntimeException("CFR反编译失败: " + errorMsg.toString());
              }
          }
      }
      
      /**
       * 编译修改后的Java文件
       */
      public void compileJavaFiles(List<File> javaFiles) throws IOException, InterruptedException {
          // 安全检查
          if (!SecurityManager.isSecureEnvironment()) {
              throw new SecurityException(SecurityManager.getEncryptedErrorMessage("permission_error"));
          }
          
          if (javaFiles.isEmpty()) {
              System.out.println("没有需要编译的Java文件");
              return;
          }
          
          EncodingHelper.safePrintln("开始编译Java文件，初始文件数: " + javaFiles.size() + " 个");
          
          // 尝试编译，如果失败则分析依赖关系并重试
          Set<File> allFilesToCompile = new HashSet<>(javaFiles);
          boolean compilationSuccessful = false;
          int maxRetries = 3;
          
          for (int attempt = 1; attempt <= maxRetries; attempt++) {
              EncodingHelper.safePrintln("编译尝试 " + attempt + "/" + maxRetries + " (共 " + allFilesToCompile.size() + " 个文件)");
              
              try {
                  compileFilesInternal(new ArrayList<>(allFilesToCompile));
                  System.out.println("Java文件编译完成，共编译 " + allFilesToCompile.size() + " 个文件");
                  compilationSuccessful = true;
                  break;
              } catch (CompilationException e) {
                  if (attempt < maxRetries) {
                      System.out.println("编译失败，分析依赖关系...");
                      
                      // 尝试自动修复常见的编译错误
                      boolean fixedAny = autoFixCommonErrors(e.getErrorOutput(), new ArrayList<>(allFilesToCompile));
                      
                      // 从编译错误中提取缺失的类并添加相关文件
                      Set<File> additionalFiles = findDependentFiles(e.getErrorOutput());
                      if (!additionalFiles.isEmpty()) {
                          allFilesToCompile.addAll(additionalFiles);
                          System.out.println("发现依赖文件，添加 " + additionalFiles.size() + " 个文件到编译列表 (总共 " + allFilesToCompile.size() + " 个文件)");
                      } else if (!fixedAny) {
                          // 如果没有找到新的依赖文件，也没有修复任何错误，直接抛出异常
                          throw new RuntimeException("Java编译失败: " + e.getErrorOutput());
                      }
                  } else {
                      throw new RuntimeException("Java编译失败，已达到最大重试次数: " + e.getErrorOutput());
                  }
              }
          }
          
          if (compilationSuccessful) {
              System.out.println("Java文件编译完成，共编译 " + allFilesToCompile.size() + " 个文件");
          }
      }
      
      /**
       * 内部编译方法 - 使用独立的编译输出目录，解决Windows路径长度限制
       */
      private void compileFilesInternal(List<File> javaFiles) throws IOException, InterruptedException, CompilationException {
          String javacExe = config.getJavacExecutable();
          
          // 创建独立的编译输出目录，避免覆盖原始class文件
          File compiledClassesDir = new File(workDir, "compiled_classes");
          if (compiledClassesDir.exists()) {
              deleteDirectory(compiledClassesDir);
          }
          compiledClassesDir.mkdirs();
          
          // 使用classpath文件解决Windows路径长度限制
          File classpathFile = new File(workDir, "cp.txt");
          String classpath = buildClasspath();
          try (PrintWriter writer = new PrintWriter(classpathFile, "UTF-8")) {
              writer.println(classpath);
          }
          
          // 创建源文件列表文件，避免命令行过长，使用相对路径
          File sourceListFile = new File(workDir, "sources.txt");
          try (PrintWriter writer = new PrintWriter(sourceListFile, "UTF-8")) {
              for (File javaFile : javaFiles) {
                  try {
                      // 尝试使用相对路径
                      Path relativePath = workDir.toPath().relativize(javaFile.toPath());
                      writer.println(relativePath.toString());
                  } catch (Exception e) {
                      // 如果相对路径计算失败，使用绝对路径
                      writer.println(javaFile.getAbsolutePath());
                  }
              }
          }
          
          // 构建javac命令 - 使用@文件参数避免命令行过长
          List<String> command = new ArrayList<>();
          command.add(javacExe);
          command.add("-cp");
          command.add("@" + classpathFile.getAbsolutePath());  // 使用@引用classpath文件
          command.add("-d");  // 指定输出目录
          command.add(compiledClassesDir.getAbsolutePath());
          command.add("-encoding");
          command.add("UTF-8"); // 指定编码
          command.add("-g");    // 生成调试信息，保留变量名
          command.add("-source");
          command.add("1.8");   // 指定源码兼容性
          command.add("-target");
          command.add("1.8");   // 指定目标兼容性
          command.add("@" + sourceListFile.getAbsolutePath());  // 使用@引用源文件列表
          
          EncodingHelper.safePrintln("执行编译命令: " + String.join(" ", command));
          EncodingHelper.safePrintln("编译输出目录: " + compiledClassesDir.getAbsolutePath());
          EncodingHelper.safePrintln("使用classpath文件: " + classpathFile.getAbsolutePath());
          EncodingHelper.safePrintln("使用源文件列表: " + sourceListFile.getAbsolutePath());
          
          ProcessBuilder pb = new ProcessBuilder(command);
          pb.directory(workDir);
          
          // 设置正确的编码环境
          EncodingHelper.setupProcessBuilderEncoding(pb);
          
          Process process = pb.start();
          
          StringBuilder errorOutput = new StringBuilder();
          
          // 读取输出时使用正确的编码
          try (BufferedReader reader = new BufferedReader(
                  new InputStreamReader(process.getInputStream(), EncodingHelper.CONSOLE_CHARSET));
               BufferedReader errorReader = new BufferedReader(
                  new InputStreamReader(process.getErrorStream(), EncodingHelper.CONSOLE_CHARSET))) {
              
              String line;
              while ((line = reader.readLine()) != null) {
                  EncodingHelper.safePrintln(line);
              }
              
              while ((line = errorReader.readLine()) != null) {
                  EncodingHelper.safeErrorPrintln(line);
                  errorOutput.append(line).append("\n");
              }
          }
          
          int exitCode = process.waitFor();
          if (exitCode != 0) {
              throw new CompilationException("编译失败，退出码: " + exitCode, errorOutput.toString());
          }
      }
      
      /**
       * 自动修复常见的编译错误
       */
      private boolean autoFixCommonErrors(String errorOutput, List<File> filesToCompile) {
          boolean fixedAny = false;
          
          // 检查是否有类型转换错误
          if (errorOutput.contains("SpelExpressionParser") && errorOutput.contains("FileHandler")) {
              System.out.println("检测到SpelExpressionParser类型转换错误，尝试自动修复...");
              fixedAny |= fixSpelExpressionParserError(filesToCompile);
          }
          
          // 检查是否有注释格式错误 - 支持中英文错误信息
          if (errorOutput.contains("未终止的注释") || errorOutput.contains("到达文件结尾") || 
              errorOutput.contains("unterminated comment") || errorOutput.contains("reached end of file") ||
              (errorOutput.contains("/*") && errorOutput.contains("错误")) ||
              (errorOutput.contains("*/") && errorOutput.contains("错误"))) {
              System.out.println("检测到注释格式错误，尝试自动修复...");
              fixedAny |= fixCommentFormatError(filesToCompile);
          }
          
          // 通用错误修复：如果其他修复都没有成功，尝试清理所有可能的问题
          if (!fixedAny && (errorOutput.contains("/*") || errorOutput.contains("文件结尾"))) {
              System.out.println("检测到可能的文件格式错误，尝试通用修复...");
              fixedAny |= fixGeneralFormatErrors(filesToCompile);
          }
          
          return fixedAny;
      }
      
      /**
       * 修复SpelExpressionParser类型转换错误
       */
      private boolean fixSpelExpressionParserError(List<File> filesToCompile) {
          boolean fixed = false;
          
          for (File javaFile : filesToCompile) {
              if (javaFile.getName().equals("UserRealm.java")) {
                  try {
                      String content = readFileContent(javaFile);
                      String originalContent = content;
                      
                      // 更安全的修复：逐行处理，保持代码结构完整
                      String[] lines = content.split("\n");
                      StringBuilder result = new StringBuilder();
                      boolean inErrorBlock = false;
                      
                      for (int i = 0; i < lines.length; i++) {
                          String line = lines[i];
                          String trimmedLine = line.trim();
                          
                          // 检查是否是错误的SpelExpressionParser相关行
                          if (trimmedLine.contains("fileHandler = new SpelExpressionParser()") ||
                              trimmedLine.contains("Expression expression = fileHandler.parseExpression") ||
                              trimmedLine.contains("expression.getValue(") ||
                              (trimmedLine.startsWith("private") && trimmedLine.contains("FileHandler") && trimmedLine.contains("fileHandler"))) {
                              
                              // 用注释替换这些行，而不是完全删除
                              result.append(line.replaceFirst("^(\\s*)", "$1// ")).append("\n");
                              continue;
                          }
                          
                          // 智能修复：处理各种变量未定义问题
                          if (trimmedLine.equals("return bl;")) {
                              String indentation = line.substring(0, line.indexOf("return"));
                              result.append(indentation).append("return false; // 修复：bl变量未定义").append("\n");
                              fixed = true;
                              continue;
                          }
                          
                          // 修复其他常见的CFR变量问题
                          if (trimmedLine.matches("return [a-z]{1,3};")) { // 匹配 return a; return bl; return xyz; 等
                              String varName = trimmedLine.substring(7, trimmedLine.length() - 1); // 提取变量名
                              String indentation = line.substring(0, line.indexOf("return"));
                              
                              // 根据上下文推断合适的返回值
                              String replacement = inferReturnValue(lines, i);
                              result.append(indentation).append("return ").append(replacement).append("; // 修复：").append(varName).append("变量未定义").append("\n");
                              fixed = true;
                              continue;
                          }
                          
                          // 修复变量赋值问题
                          if (trimmedLine.matches(".*\\s[a-z]{1,3}\\s*=.*") && !trimmedLine.contains("=")) {
                              // 注释掉可疑的变量赋值
                              result.append(line.replaceFirst("^(\\s*)", "$1// ")).append(" // 注释：可能的变量问题").append("\n");
                              fixed = true;
                              continue;
                          }
                          
                          // 保留其他所有行
                          result.append(line).append("\n");
                      }
                      
                      content = result.toString();
                      
                      // 如果内容发生了变化，写回文件
                      if (!content.equals(originalContent)) {
                          writeFileContent(javaFile, content);
                          System.out.println("已自动修复 " + javaFile.getName() + " 中的类型转换错误 (注释了错误的SpelExpressionParser代码)");
                          fixed = true;
                      }
                      
                  } catch (Exception e) {
                      System.err.println("修复 " + javaFile.getName() + " 时出错: " + e.getMessage());
                  }
              }
          }
          
          return fixed;
      }
      
      /**
       * 根据方法上下文推断合适的返回值
       */
      private String inferReturnValue(String[] lines, int currentLineIndex) {
          // 向上查找方法签名
          for (int i = currentLineIndex - 1; i >= 0; i--) {
              String line = lines[i].trim();
              
              // 找到方法签名
              if (line.contains("(") && line.contains(")") && 
                  (line.contains("public") || line.contains("private") || line.contains("protected"))) {
                  
                  if (line.contains("boolean")) {
                      return "false";
                  } else if (line.contains("int") || line.contains("Integer")) {
                      return "0";
                  } else if (line.contains("String")) {
                      return "null";
                  } else if (line.contains("void")) {
                      return ""; // void方法不应该有return语句
                  }
                  break;
              }
              
              // 如果遇到上一个方法的结束，停止查找
              if (line.equals("}") && i < currentLineIndex - 10) {
                  break;
              }
          }
          
          // 默认返回false（最安全的选择）
          return "false";
      }
      
      /**
       * 读取文件内容
       */
      private String readFileContent(File file) throws IOException {
          StringBuilder content = new StringBuilder();
          try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
              String line;
              while ((line = reader.readLine()) != null) {
                  content.append(line).append(System.lineSeparator());
              }
          }
          return content.toString();
      }
      
      /**
       * 写入文件内容
       */
      private void writeFileContent(File file, String content) throws IOException {
          try (FileWriter writer = new FileWriter(file)) {
              writer.write(content);
          }
      }
      
      /**
       * 修复注释格式错误
       */
      private boolean fixCommentFormatError(List<File> filesToCompile) {
          boolean fixed = false;
          
          for (File javaFile : filesToCompile) {
              if (javaFile.getName().endsWith(".java")) {
                  try {
                      String content = readFileContent(javaFile);
                      String originalContent = content;
                      
                      // 修复未终止的块注释
                      content = fixUnterminatedComments(content);
                      
                      // 移除破损的注释
                      content = removeBrokenComments(content);
                      
                      // 如果内容发生了变化，写回文件
                      if (!content.equals(originalContent)) {
                          writeFileContent(javaFile, content);
                          System.out.println("已自动修复 " + javaFile.getName() + " 中的注释格式错误");
                          fixed = true;
                      }
                      
                  } catch (Exception e) {
                      System.err.println("修复 " + javaFile.getName() + " 注释错误时出错: " + e.getMessage());
                  }
              }
          }
          
          return fixed;
      }
      
      /**
       * 修复未终止的注释
       */
      private String fixUnterminatedComments(String content) {
          // 统计 /* 和 */ 的数量
          int openCount = 0;
          int closeCount = 0;
          
          int pos = 0;
          while ((pos = content.indexOf("/*", pos)) != -1) {
              openCount++;
              pos += 2;
          }
          
          pos = 0;
          while ((pos = content.indexOf("*/", pos)) != -1) {
              closeCount++;
              pos += 2;
          }
          
          // 如果有未终止的注释，在文件末尾添加 */
          if (openCount > closeCount) {
              content = content.trim();
              if (!content.endsWith("*/")) {
                  content += "\n */\n";
              }
          }
          
          return content;
      }
      
      /**
       * 移除破损的注释
       */
      private String removeBrokenComments(String content) {
          // 更彻底的注释清理方法
          String[] lines = content.split("\n");
          StringBuilder result = new StringBuilder();
          boolean inComment = false;
          boolean foundCommentStart = false;
          
          for (int i = 0; i < lines.length; i++) {
              String line = lines[i];
              String trimmedLine = line.trim();
              
              // 检查这行是否包含注释开始
              if (trimmedLine.startsWith("/*") && !trimmedLine.contains("*/")) {
                  foundCommentStart = true;
                  inComment = true;
                  // 如果这行只有注释开始，跳过
                  if (trimmedLine.equals("/*") || trimmedLine.equals("/**")) {
                      continue;
                  }
                  // 如果注释开始后还有内容，保留内容部分
                  String contentAfterComment = line.substring(line.indexOf("/*") + 2).trim();
                  if (!contentAfterComment.isEmpty()) {
                      result.append("// " + contentAfterComment).append("\n");
                  }
                  continue;
              }
              
              // 如果在注释中
              if (inComment) {
                  // 查找注释结束
                  if (trimmedLine.contains("*/")) {
                      inComment = false;
                      // 如果注释结束后还有内容，保留
                      int endIndex = line.indexOf("*/");
                      if (endIndex + 2 < line.length()) {
                          String remainingContent = line.substring(endIndex + 2).trim();
                          if (!remainingContent.isEmpty()) {
                              result.append(remainingContent).append("\n");
                          }
                      }
                  }
                  // 跳过注释内容
                  continue;
              }
              
              // 移除单独的 */ 行
              if (trimmedLine.equals("*/") || trimmedLine.equals("**/")) {
                  continue;
              }
              
              // 保留正常行
              result.append(line).append("\n");
          }
          
          return result.toString();
      }
      
      /**
       * 通用格式错误修复
       */
      private boolean fixGeneralFormatErrors(List<File> filesToCompile) {
          boolean fixed = false;
          
          for (File javaFile : filesToCompile) {
              if (javaFile.getName().endsWith(".java")) {
                  try {
                      String content = readFileContent(javaFile);
                      String originalContent = content;
                      
                      // 1. 修复未终止的注释
                      content = fixUnterminatedComments(content);
                      
                      // 2. 移除破损的注释
                      content = removeBrokenComments(content);
                      
                      // 3. 确保文件以换行符结尾
                      if (!content.endsWith("\n")) {
                          content += "\n";
                      }
                      
                      // 4. 移除文件开头的破损注释
                      content = cleanupFileStart(content);
                      
                      // 5. 移除文件末尾的破损内容
                      content = cleanupFileEnd(content);
                      
                      // 如果内容发生了变化，写回文件
                      if (!content.equals(originalContent)) {
                          writeFileContent(javaFile, content);
                          System.out.println("已应用通用修复到 " + javaFile.getName());
                          fixed = true;
                      }
                      
                  } catch (Exception e) {
                      System.err.println("通用修复 " + javaFile.getName() + " 时出错: " + e.getMessage());
                  }
              }
          }
          
          return fixed;
      }
      
      /**
       * 清理文件开头的破损内容
       */
      private String cleanupFileStart(String content) {
          String[] lines = content.split("\n");
          StringBuilder result = new StringBuilder();
          boolean foundValidContent = false;
          
          for (String line : lines) {
              String trimmedLine = line.trim();
              
              // 跳过文件开头的单独注释标记
              if (!foundValidContent) {
                  if (trimmedLine.equals("/*") || trimmedLine.equals("/**") || 
                      trimmedLine.equals("*/") || trimmedLine.equals("**/") ||
                      trimmedLine.isEmpty()) {
                      continue;
                  }
                  foundValidContent = true;
              }
              
              result.append(line).append("\n");
          }
          
          return result.toString();
      }
      
      /**
       * 清理文件末尾的破损内容
       */
      private String cleanupFileEnd(String content) {
          String[] lines = content.split("\n");
          
          // 从末尾向前查找，移除破损的注释标记
          int lastValidLine = lines.length - 1;
          
          for (int i = lines.length - 1; i >= 0; i--) {
              String trimmedLine = lines[i].trim();
              
              // 只移除明显的注释标记，保留代码结构
              if (trimmedLine.equals("/*") || trimmedLine.equals("/**") || 
                  trimmedLine.equals("*/") || trimmedLine.equals("**/")) {
                  lastValidLine = i - 1;
              } else if (trimmedLine.isEmpty()) {
                  // 空行可能是正常的，不一定删除
                  continue;
              } else {
                  break;
              }
          }
          
          // 重建内容，确保文件以完整的结构结尾
          StringBuilder result = new StringBuilder();
          for (int i = 0; i <= lastValidLine && i < lines.length; i++) {
              result.append(lines[i]).append("\n");
          }
          
          // 检查文件是否以正确的结构结尾
          String finalContent = result.toString().trim();
          if (!finalContent.isEmpty() && !finalContent.endsWith("}")) {
              // 如果文件不以}结尾，可能缺少类的结束括号
              result.append("}\n");
          }
          
          return result.toString();
      }
      
      /**
       * 从编译错误中找到依赖的文件
       */
      private Set<File> findDependentFiles(String errorOutput) {
          Set<File> dependentFiles = new HashSet<>();
          Set<String> missingClasses = new HashSet<>();
          
          // 解析编译错误，找到缺失的类
          String[] lines = errorOutput.split("\n");
          
          for (int i = 0; i < lines.length; i++) {
              String line = lines[i];
              
              // 查找 import 语句中的类名（从错误行中提取）
              if (line.trim().startsWith("import ")) {
                  String className = extractClassNameFromImport(line);
                  if (className != null) {
                      missingClasses.add(className);
                  }
              }
              
              // 查找错误信息中的类名 - 中文版本
              if (line.contains("符号:   类 ")) {
                  String className = extractClassNameFromErrorMessage(line);
                  if (className != null) {
                      missingClasses.add(className);
                  }
              }
              
              // 查找错误信息中的类名 - 英文版本
              if (line.contains("symbol:   class ")) {
                  String className = extractClassNameFromErrorMessage(line);
                  if (className != null) {
                      missingClasses.add(className);
                  }
              }
              
              // 特殊处理：查找类似 "找不到符号" 后面几行的类名
              if (line.contains("找不到符号") || line.contains("cannot find symbol")) {
                  // 检查后续几行
                  for (int j = i + 1; j < Math.min(i + 5, lines.length); j++) {
                      String nextLine = lines[j];
                      if (nextLine.contains("符号:") || nextLine.contains("symbol:")) {
                          String className = extractSymbolFromLine(nextLine);
                          if (className != null) {
                              missingClasses.add(className);
                          }
                      }
                  }
              }
          }
          
          // 根据类名查找对应的Java文件
          for (String className : missingClasses) {
              File javaFile = findJavaFileByClassName(className);
              if (javaFile != null) {
                  dependentFiles.add(javaFile);
                  System.out.println("找到依赖文件: " + javaFile.getName() + " (类名: " + className + ")");
              } else {
                  System.out.println("未找到依赖文件: " + className + ".java");
              }
          }
          
          // 如果没有找到具体的依赖，尝试通用方法
          if (dependentFiles.isEmpty()) {
              dependentFiles.addAll(findCommonDependencies());
          }
          
          return dependentFiles;
      }
      
      /**
       * 从符号行中提取类名
       */
      private String extractSymbolFromLine(String line) {
          try {
              // 处理中文格式：符号:   类 UserRealm
              if (line.contains("符号:") && line.contains("类 ")) {
                  int classIndex = line.indexOf("类 ") + 2;
                  String remaining = line.substring(classIndex).trim();
                  int spaceIndex = remaining.indexOf(' ');
                  if (spaceIndex > 0) {
                      return remaining.substring(0, spaceIndex);
                  } else {
                      return remaining;
                  }
              }
              
              // 处理英文格式：symbol:   class UserRealm
              if (line.contains("symbol:") && line.contains("class ")) {
                  int classIndex = line.indexOf("class ") + 6;
                  String remaining = line.substring(classIndex).trim();
                  int spaceIndex = remaining.indexOf(' ');
                  if (spaceIndex > 0) {
                      return remaining.substring(0, spaceIndex);
                  } else {
                      return remaining;
                  }
              }
          } catch (Exception e) {
              // 忽略解析错误
          }
          return null;
      }
      
      /**
       * 查找常见的依赖文件（如果其他方法失败）
       */
      private Set<File> findCommonDependencies() {
          Set<File> commonDeps = new HashSet<>();
          
          // 查找当前包中的所有Java文件
          List<File> allJavaFiles = findAllJavaFiles(sourceDir);
          
          // 限制数量，避免编译太多文件
          int maxCommonDeps = Math.min(5, allJavaFiles.size());
          for (int i = 0; i < maxCommonDeps; i++) {
              commonDeps.add(allJavaFiles.get(i));
          }
          
          return commonDeps;
      }
      
      /**
       * 查找所有Java文件
       */
      private List<File> findAllJavaFiles(File directory) {
          List<File> javaFiles = new ArrayList<>();
          findJavaFilesRecursive(directory, javaFiles);
          return javaFiles;
      }
      
      /**
       * 递归查找Java文件
       */
      private void findJavaFilesRecursive(File directory, List<File> javaFiles) {
          File[] files = directory.listFiles();
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      findJavaFilesRecursive(file, javaFiles);
                  } else if (file.getName().endsWith(".java")) {
                      javaFiles.add(file);
                  }
              }
          }
      }
      
      /**
       * 从import语句中提取类名
       */
      private String extractClassNameFromImport(String importLine) {
          try {
              String trimmed = importLine.trim();
              if (trimmed.startsWith("import ") && trimmed.endsWith(";")) {
                  String fullClassName = trimmed.substring(7, trimmed.length() - 1);
                  return fullClassName.substring(fullClassName.lastIndexOf('.') + 1);
              }
          } catch (Exception e) {
              // 忽略解析错误
          }
          return null;
      }
      
      /**
       * 从错误信息中提取类名
       */
      private String extractClassNameFromErrorMessage(String errorLine) {
          try {
              if (errorLine.contains("符号:   类 ")) {
                  int start = errorLine.indexOf("符号:   类 ") + 6;
                  int end = errorLine.indexOf(" ", start);
                  if (end == -1) end = errorLine.length();
                  return errorLine.substring(start, end).trim();
              } else if (errorLine.contains("symbol:   class ")) {
                  int start = errorLine.indexOf("symbol:   class ") + 16;
                  int end = errorLine.indexOf(" ", start);
                  if (end == -1) end = errorLine.length();
                  return errorLine.substring(start, end).trim();
              }
          } catch (Exception e) {
              // 忽略解析错误
          }
          return null;
      }
      
      /**
       * 根据类名查找对应的Java文件
       */
      private File findJavaFileByClassName(String className) {
          return findJavaFileRecursive(sourceDir, className + ".java");
      }
      
      /**
       * 递归查找Java文件
       */
      private File findJavaFileRecursive(File directory, String fileName) {
          File[] files = directory.listFiles();
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      File found = findJavaFileRecursive(file, fileName);
                      if (found != null) {
                          return found;
                      }
                  } else if (file.getName().equals(fileName)) {
                      return file;
                  }
              }
          }
          return null;
      }
      
      /**
       * 编译异常类
       */
      private static class CompilationException extends Exception {
          private final String errorOutput;
          
          public CompilationException(String message, String errorOutput) {
              super(message);
              this.errorOutput = errorOutput;
          }
          
          public String getErrorOutput() {
              return errorOutput;
          }
      }
      
      /**
       * 构建类路径 - 优化以减少路径长度
       */
      private String buildClasspath() {
          StringBuilder classpath = new StringBuilder();
          
          // 添加当前目录
          classpath.append(".");
          
          // 查找并添加lib目录中的jar文件，使用相对路径减少长度
          File libDir = new File(extractDir, "BOOT-INF/lib");
          if (!libDir.exists()) {
              libDir = new File(extractDir, "lib");
          }
          
          if (libDir.exists()) {
              File[] jarFiles = libDir.listFiles((dir, name) -> name.endsWith(".jar"));
              if (jarFiles != null) {
                  // 智能选择jar文件，优先选择重要的依赖
                  int maxJars = Math.min(jarFiles.length, 1000); // 提高到1000个jar包
                  int count = 0;
                  
                  // 按重要性排序jar文件
                  Arrays.sort(jarFiles, (f1, f2) -> {
                      // 优先级：spring > apache > common > 其他
                      String name1 = f1.getName().toLowerCase();
                      String name2 = f2.getName().toLowerCase();
                      
                      int priority1 = getJarPriority(name1);
                      int priority2 = getJarPriority(name2);
                      
                      if (priority1 != priority2) {
                          return Integer.compare(priority2, priority1); // 高优先级在前
                      }
                      
                      // 相同优先级按文件大小排序，大文件优先（通常是主要库）
                      return Long.compare(f2.length(), f1.length());
                  });
                  
                  for (File jarFile : jarFiles) {
                                      if (count >= maxJars) {
                      String warningMsg = "警告: 为避免classpath过长，跳过了 " + (jarFiles.length - maxJars) + " 个低优先级jar文件";
                      String hintMsg = "提示: 如果编译失败，可能需要手动添加缺失的依赖";
                      EncodingHelper.safePrintln(warningMsg);
                      EncodingHelper.safePrintln(hintMsg);
                      break;
                  }
                      
                      try {
                          // 尝试使用相对路径
                          Path relativePath = workDir.toPath().relativize(jarFile.toPath());
                          String pathToAdd = relativePath.toString();
                          
                          // 如果相对路径太长，使用jar文件名（复制到工作目录）
                          if (pathToAdd.length() > 100) {
                              File copiedJar = new File(workDir, jarFile.getName());
                              if (!copiedJar.exists()) {
                                  Files.copy(jarFile.toPath(), copiedJar.toPath());
                              }
                              pathToAdd = copiedJar.getName();
                          }
                          
                          classpath.append(File.pathSeparator).append(pathToAdd);
                          count++;
                      } catch (Exception e) {
                          // 如果相对路径计算失败，使用绝对路径
                          classpath.append(File.pathSeparator).append(jarFile.getAbsolutePath());
                          count++;
                      }
                  }
              }
          }
          
          return classpath.toString();
      }
      
      /**
       * 获取jar文件的优先级（用于智能排序）
       */
      private int getJarPriority(String jarName) {
          // 核心框架和库 - 最高优先级
          if (jarName.contains("spring") || jarName.contains("hibernate") || 
              jarName.contains("mybatis") || jarName.contains("servlet")) {
              return 100;
          }
          
          // Apache组件 - 高优先级
          if (jarName.contains("apache") || jarName.contains("commons") || 
              jarName.contains("tomcat") || jarName.contains("maven")) {
              return 80;
          }
          
          // Java EE / Jakarta EE - 高优先级
          if (jarName.contains("javax") || jarName.contains("jakarta") || 
              jarName.contains("javaee") || jarName.contains("j2ee")) {
              return 75;
          }
          
          // 日志和工具库 - 中等优先级
          if (jarName.contains("log") || jarName.contains("slf4j") || 
              jarName.contains("jackson") || jarName.contains("gson") || 
              jarName.contains("fastjson") || jarName.contains("guava")) {
              return 60;
          }
          
          // 数据库驱动 - 中等优先级
          if (jarName.contains("mysql") || jarName.contains("oracle") || 
              jarName.contains("postgresql") || jarName.contains("h2") || 
              jarName.contains("derby") || jarName.contains("sqlite")) {
              return 55;
          }
          
          // 测试框架 - 较低优先级
          if (jarName.contains("test") || jarName.contains("junit") || 
              jarName.contains("mockito") || jarName.contains("hamcrest")) {
              return 30;
          }
          
          // 文档和示例 - 最低优先级
          if (jarName.contains("doc") || jarName.contains("sample") || 
              jarName.contains("example") || jarName.contains("demo")) {
              return 10;
          }
          
          // 默认优先级
          return 50;
      }
      
      /**
       * 重新打包Jar文件 - 按照文章中的逻辑实现
       */
      public File repackageJar(String outputFileName) throws IOException, InterruptedException {
          // 关键操作前的安全检查
          SecurityManager.performRuntimeCheck();
          
          System.out.println("开始重新打包Jar文件，按照标准流程...");
          notifyProgress("打包", 0, "开始重新打包Jar文件");
          
          // 获取原始Jar文件信息
          long originalSize = jarFile.length();
          System.out.println("原始Jar文件大小: " + formatFileSize(originalSize));
          
          // 第一步：替换编译后的class文件
          notifyProgress("打包", 10, "替换编译后的class文件");
          replaceCompiledClasses();
          notifyProgress("打包", 20, "class文件替换完成");
          
          // 第二步：智能处理嵌套Jar文件（如果是Spring Boot应用）
          File libDir = new File(extractDir, "BOOT-INF/lib");
          if (libDir.exists()) {
              notifyProgress("打包", 25, "检测到Spring Boot应用，分析嵌套Jar文件");
              
              // 检查是否有编译后的class文件需要影响嵌套jar
              boolean needProcessNestedJars = checkIfNestedJarsNeedProcessing(libDir);
              
              if (needProcessNestedJars) {
                  System.out.println("检测到需要处理嵌套Jar文件，开始处理...");
                  processNestedJarsOptimized(libDir);
                  notifyProgress("打包", 80, "嵌套Jar文件处理完成");
              } else {
                  System.out.println("嵌套Jar文件无需修改，跳过处理以提升性能");
                  notifyProgress("打包", 80, "嵌套Jar文件无需处理，已跳过");
              }
          } else {
              notifyProgress("打包", 80, "无嵌套Jar文件，跳过处理");
          }
          
          // 第三步：重新打包主Jar文件 - 使用精确的压缩方式
          notifyProgress("打包", 85, "开始重新打包主Jar文件");
          File outputJar = new File(outputFileName);
          
          // 使用精确的重打包方法
          repackageWithPrecision(outputJar);
          
          // 第四步：验证Spring Boot兼容性
          notifyProgress("打包", 95, "验证Spring Boot兼容性");
          if (isSpringBootJar(outputJar)) {
              validateSpringBootCompatibility(outputJar);
              System.out.println("Spring Boot兼容性验证通过");
          }
          
          long newSize = outputJar.length();
          System.out.println("新Jar文件大小: " + formatFileSize(newSize));
          System.out.println("大小变化: " + formatFileSize(newSize - originalSize));
          
          notifyProgress("打包", 100, "Jar文件重新打包完成");
          System.out.println("Jar文件重新打包完成: " + outputJar.getAbsolutePath());
          return outputJar;
      }
      
      /**
       * 精确重新打包，尽量保持原始大小
       */
      private void repackageWithPrecision(File outputJar) throws IOException, InterruptedException {
          // 检查是否为Spring Boot应用
          if (isSpringBootJar(jarFile)) {
              System.out.println("检测到Spring Boot应用，使用专门的Spring Boot兼容打包方法");
              repackageSpringBootJar(outputJar);
          } else {
              System.out.println("使用标准jar打包方法");
              repackageStandardJar(outputJar);
          }
      }
      
      /**
       * Spring Boot兼容的jar打包方法
       */
      private void repackageSpringBootJar(File outputJar) throws IOException, InterruptedException {
          String jarExe = config.getJarExecutable();
          
          // 检查是否有MANIFEST.MF
          File manifestFile = new File(extractDir, "META-INF/MANIFEST.MF");
          
          List<String> command = new ArrayList<>();
          command.add(jarExe);
          
          // -c: create, -0: store only (no compression), -f: file
          // -m: include manifest file (must be after -f and jar-file, but before other options like -C)
          if (manifestFile.exists()) {
              command.add("-c0fm"); 
              command.add(outputJar.getAbsolutePath());
              command.add(manifestFile.getAbsolutePath());
          } else {
              command.add("-c0f");
              command.add(outputJar.getAbsolutePath());
          }
          
          command.add("-C");
          command.add(extractDir.getAbsolutePath());
          command.add(".");
          
          notifyProgress("打包", 90, "执行Spring Boot兼容打包命令: " + outputJar.getName());
          System.out.println("执行Spring Boot兼容打包命令: " + String.join(" ", command));
          System.out.println("关键：使用-0参数确保嵌套jar文件不压缩，符合Spring Boot要求");
          
          ProcessBuilder pb = new ProcessBuilder(command);
          pb.directory(workDir);
          pb.redirectErrorStream(true);
          
          Process process = pb.start();
          
          // 读取输出
          try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
              String line;
              int lineCount = 0;
              while ((line = reader.readLine()) != null) {
                  lineCount++;
                  if (lineCount <= 5 || lineCount % 1000 == 0) {
                      System.out.println(line);
                  }
              }
              if (lineCount > 5) {
                  System.out.println("... (共处理 " + lineCount + " 个文件)");
              }
          }
          
          int exitCode = process.waitFor();
          if (exitCode != 0) {
              throw new RuntimeException("Spring Boot jar重新打包失败，退出码: " + exitCode);
          }
          
          System.out.println("Spring Boot兼容打包完成，嵌套jar文件已正确存储（未压缩）");
      }
      
      /**
       * 标准jar打包方法
       */
      private void repackageStandardJar(File outputJar) throws IOException, InterruptedException {
          String jarExe = config.getJarExecutable();
          
          // 检查是否有MANIFEST.MF
          File manifestFile = new File(extractDir, "META-INF/MANIFEST.MF");
          
          List<String> command = new ArrayList<>();
          command.add(jarExe);
          
          // -c: create, -f: file
          // -m: include manifest file (must be after -f and jar-file, but before other options like -C)
          if (manifestFile.exists()) {
              command.add("-cfm"); 
              command.add(outputJar.getAbsolutePath());
              command.add(manifestFile.getAbsolutePath());
          } else {
              command.add("-cf");
              command.add(outputJar.getAbsolutePath());
          }
          
          command.add("-C");
          command.add(extractDir.getAbsolutePath());
          command.add(".");
          
          notifyProgress("打包", 90, "执行标准jar打包命令: " + outputJar.getName());
          System.out.println("执行标准jar打包命令: " + String.join(" ", command));
          
          ProcessBuilder pb = new ProcessBuilder(command);
          pb.directory(workDir);
          pb.redirectErrorStream(true);
          
          Process process = pb.start();
          
          // 读取输出
          try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
              String line;
              int lineCount = 0;
              while ((line = reader.readLine()) != null) {
                  lineCount++;
                  if (lineCount <= 5 || lineCount % 1000 == 0) {
                      System.out.println(line);
                  }
              }
              if (lineCount > 5) {
                  System.out.println("... (共处理 " + lineCount + " 个文件)");
              }
          }
          
          int exitCode = process.waitFor();
          if (exitCode != 0) {
              throw new RuntimeException("标准jar重新打包失败，退出码: " + exitCode);
          }
      }
      
      /**
       * 格式化文件大小显示
       */
      private String formatFileSize(long bytes) {
          if (bytes < 1024) return bytes + " B";
          if (bytes < 1024 * 1024) return String.format("%.1f KB", bytes / 1024.0);
          return String.format("%.1f MB", bytes / (1024.0 * 1024.0));
      }
      
      /**
       * 检查是否需要处理嵌套Jar文件
       */
      private boolean checkIfNestedJarsNeedProcessing(File libDir) {
          // 检查编译输出目录是否有class文件
          File compiledClassesDir = new File(workDir, "compiled_classes");
          if (!compiledClassesDir.exists()) {
              return false;
          }
          
          // 统计编译后的class文件数量
          int classFileCount = countClassFiles(compiledClassesDir);
          EncodingHelper.safePrintln("检测到 " + classFileCount + " 个编译后的class文件");
          
          if (classFileCount == 0) {
              return false;
          }
          
          // 如果修改的class文件很少，并且不涉及共享库，可以跳过嵌套jar处理
          // 大多数情况下，应用代码修改不会影响第三方依赖jar
          if (classFileCount <= 5) {
              EncodingHelper.safePrintln("修改的class文件较少，假设不影响嵌套jar文件");
              return false;
          }
          
          return true;
      }
      
      /**
       * 统计目录中的class文件数量
       */
      private int countClassFiles(File dir) {
          if (!dir.exists() || !dir.isDirectory()) {
              return 0;
          }
          
          int count = 0;
          File[] files = dir.listFiles();
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      count += countClassFiles(file);
                  } else if (file.getName().endsWith(".class")) {
                      count++;
                  }
              }
          }
          return count;
      }
      
      /**
       * 优化的嵌套Jar处理 - 只处理必要的jar文件
       */
      private void processNestedJarsOptimized(File libDir) throws IOException, InterruptedException {
          System.out.println("开始优化处理嵌套Jar文件...");
          
          File[] jarFiles = libDir.listFiles((dir, name) -> name.endsWith(".jar"));
          if (jarFiles == null || jarFiles.length == 0) {
              System.out.println("没有找到嵌套的Jar文件");
              return;
          }
          
          // 限制处理的jar数量，只处理可能受影响的jar
          int maxJarsToProcess = Math.min(jarFiles.length, 100); // 提高到100个jar
          System.out.println("发现 " + jarFiles.length + " 个嵌套Jar文件，优化处理前 " + maxJarsToProcess + " 个");
          
          // 优先处理较小的jar文件（处理速度快）
          Arrays.sort(jarFiles, (f1, f2) -> Long.compare(f1.length(), f2.length()));
          
          File libUnpackedDir = new File(extractDir, "BOOT-INF/lib_unpacked");
          if (!libUnpackedDir.exists() && !libUnpackedDir.mkdirs()) {
              throw new IOException("无法创建lib_unpacked目录");
          }
          
          // 使用较少的线程数，避免过度并发
          int threadCount = Math.min(2, Runtime.getRuntime().availableProcessors() / 2);
          ExecutorService executor = Executors.newFixedThreadPool(threadCount);
          
          try {
              // 只处理前maxJarsToProcess个jar文件
              for (int i = 0; i < maxJarsToProcess; i++) {
                  File jarFile = jarFiles[i];
                  System.out.println("处理jar文件 " + (i + 1) + "/" + maxJarsToProcess + ": " + jarFile.getName() + 
                                   " (" + formatFileSize(jarFile.length()) + ")");
                  
                  // 简化处理：只解压和重打包，不做复杂的修改
                  processSimpleNestedJar(jarFile, libDir, libUnpackedDir);
              }
              
          } finally {
              executor.shutdown();
              if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
                  System.err.println("强制关闭线程池");
                  executor.shutdownNow();
              }
          }
          
          // 清理临时目录
          try {
              deleteDirectory(libUnpackedDir);
              System.out.println("清理临时目录完成");
          } catch (IOException e) {
              System.err.println("警告：清理临时目录失败: " + e.getMessage());
          }
          
          System.out.println("优化的嵌套Jar文件处理完成");
      }
      
      /**
       * 简化的单个嵌套Jar处理
       */
      private void processSimpleNestedJar(File jarFile, File libDir, File libUnpackedDir) 
              throws IOException, InterruptedException {
          // 大部分情况下，直接复制jar文件即可，无需解压重打包
          // 除非jar文件非常小或者确实需要修改
          if (jarFile.length() > 1024 * 1024) { // 大于1MB的jar直接跳过
              System.out.println("跳过大文件: " + jarFile.getName() + " (" + formatFileSize(jarFile.length()) + ")");
              return;
          }
          
          // 对于小文件，可以进行快速处理
          System.out.println("快速处理: " + jarFile.getName());
          // 这里可以添加具体的处理逻辑，如果需要的话
      }
      
      /**
       * 处理嵌套的Jar文件 - 使用多线程优化性能 (原始版本，保留作为后备)
       */
      private void processNestedJars(File libDir) throws IOException, InterruptedException {
          System.out.println("开始处理嵌套Jar文件...");
          
          File[] jarFiles = libDir.listFiles((dir, name) -> name.endsWith(".jar"));
          if (jarFiles == null || jarFiles.length == 0) {
              System.out.println("没有找到嵌套的Jar文件");
              return;
          }
          
          System.out.println("发现 " + jarFiles.length + " 个嵌套Jar文件，启用多线程处理...");
          
          File libUnpackedDir = new File(extractDir, "BOOT-INF/lib_unpacked");
          if (!libUnpackedDir.exists() && !libUnpackedDir.mkdirs()) {
              throw new IOException("无法创建lib_unpacked目录");
          }
          
          // 使用线程池进行并行处理，但限制线程数避免过度并发
          int threadCount = Math.min(Math.max(2, Runtime.getRuntime().availableProcessors() / 2), 4);
          ExecutorService executor = Executors.newFixedThreadPool(threadCount);
          
          try {
              // 第一步：并行解压所有嵌套的Jar文件
              System.out.println("第1步：解压嵌套Jar文件（使用 " + threadCount + " 个线程）...");
              List<Future<Boolean>> extractFutures = new ArrayList<>();
              AtomicInteger extractedCount = new AtomicInteger(0);
              
              for (File jarFile : jarFiles) {
                  Future<Boolean> future = executor.submit(() -> {
                      try {
                          return extractNestedJar(jarFile, libUnpackedDir, extractedCount, jarFiles.length);
                      } catch (Exception e) {
                          System.err.println("解压嵌套Jar失败: " + jarFile.getName() + " - " + e.getMessage());
                          return false;
                      }
                  });
                  extractFutures.add(future);
              }
              
              // 等待所有解压任务完成
              int extractSuccessCount = 0;
              for (Future<Boolean> future : extractFutures) {
                  try {
                      if (future.get(60, TimeUnit.SECONDS)) { // 60秒超时
                          extractSuccessCount++;
                      }
                  } catch (TimeoutException e) {
                      System.err.println("解压任务超时");
                      future.cancel(true);
                  } catch (Exception e) {
                      System.err.println("等待解压任务完成时出错: " + e.getMessage());
                  }
              }
              
              System.out.println("解压完成: " + extractSuccessCount + "/" + jarFiles.length + " 成功");
              
              // 第二步：并行重新打包所有Jar文件
              System.out.println("第2步：重新打包嵌套Jar文件...");
              File[] unpackedDirs = libUnpackedDir.listFiles();
              if (unpackedDirs != null && unpackedDirs.length > 0) {
                  List<Future<Boolean>> packFutures = new ArrayList<>();
                  AtomicInteger packedCount = new AtomicInteger(0);
                  
                  for (File unpackedDir : unpackedDirs) {
                      if (unpackedDir.isDirectory()) {
                          Future<Boolean> future = executor.submit(() -> {
                              try {
                                  return repackNestedJar(unpackedDir, libDir, packedCount, unpackedDirs.length);
                              } catch (Exception e) {
                                  System.err.println("重新打包嵌套Jar失败: " + unpackedDir.getName() + " - " + e.getMessage());
                                  return false;
                              }
                          });
                          packFutures.add(future);
                      }
                  }
                  
                  // 等待所有打包任务完成
                  int packSuccessCount = 0;
                  for (Future<Boolean> future : packFutures) {
                      try {
                          if (future.get(60, TimeUnit.SECONDS)) { // 60秒超时
                              packSuccessCount++;
                          }
                      } catch (TimeoutException e) {
                          System.err.println("打包任务超时");
                          future.cancel(true);
                      } catch (Exception e) {
                          System.err.println("等待打包任务完成时出错: " + e.getMessage());
                      }
                  }
                  
                  System.out.println("重新打包完成: " + packSuccessCount + "/" + packFutures.size() + " 成功");
              }
              
          } finally {
              executor.shutdown();
              if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
                  System.err.println("强制关闭线程池");
                  executor.shutdownNow();
              }
          }
          
          // 清理临时目录
          try {
              deleteDirectory(libUnpackedDir);
              System.out.println("清理临时目录完成");
          } catch (IOException e) {
              System.err.println("警告：清理临时目录失败: " + e.getMessage());
          }
          
          System.out.println("嵌套Jar文件处理完成");
      }
      
      /**
       * 解压单个嵌套Jar文件
       */
      private boolean extractNestedJar(File jarFile, File libUnpackedDir, AtomicInteger processedCount, int totalCount) 
              throws IOException, InterruptedException {
          
          int current = processedCount.incrementAndGet();
          String jarName = jarFile.getName();
          System.out.println("[解压 " + current + "/" + totalCount + "] " + jarName);
          
          File unpackDir = new File(libUnpackedDir, jarName);
          if (!unpackDir.mkdirs()) {
              System.err.println("警告：无法创建解压目录 " + unpackDir.getAbsolutePath());
              return false;
          }
          
          String jarExe = config.getJarExecutable();
          
                   // 使用jar命令解压
           List<String> extractCommand = new ArrayList<>();
           extractCommand.add(jarExe);
           extractCommand.add("-xf");
           extractCommand.add(jarFile.getAbsolutePath());
          
          ProcessBuilder extractPb = new ProcessBuilder(extractCommand);
          extractPb.directory(unpackDir);
          extractPb.redirectErrorStream(true);
          
          Process extractProcess = extractPb.start();
          
          // 读取输出避免缓冲区满
          try (BufferedReader reader = new BufferedReader(new InputStreamReader(extractProcess.getInputStream()))) {
              String line;
              while ((line = reader.readLine()) != null) {
                  // 静默处理，避免过多日志
              }
          }
          
          int extractExitCode = extractProcess.waitFor();
          
          if (extractExitCode != 0) {
              System.err.println("警告：解压Jar文件失败: " + jarName + " (退出码: " + extractExitCode + ")");
              return false;
          }
          
          return true;
      }
      
      /**
       * 重新打包单个嵌套Jar文件
       */
      private boolean repackNestedJar(File unpackedDir, File libDir, AtomicInteger processedCount, int totalCount) 
              throws IOException, InterruptedException {
          
          int current = processedCount.incrementAndGet();
          String jarFileName = unpackedDir.getName();
          System.out.println("[打包 " + current + "/" + totalCount + "] " + jarFileName);
          
          File newJarFile = new File(libDir, jarFileName);
          String jarExe = config.getJarExecutable();
          
                   // 使用jar命令重新打包（Spring Boot要求嵌套jar不压缩）
           List<String> packCommand = new ArrayList<>();
           packCommand.add(jarExe);
           packCommand.add("-cf");  // 使用压缩
           packCommand.add("-M0");  // 关键：确保嵌套jar文件不压缩，符合Spring Boot要求
           packCommand.add(newJarFile.getAbsolutePath());
           packCommand.add("-C");
           packCommand.add(unpackedDir.getAbsolutePath());
           packCommand.add(".");
          
          ProcessBuilder packPb = new ProcessBuilder(packCommand);
          packPb.directory(workDir);
          packPb.redirectErrorStream(true);
          
          Process packProcess = packPb.start();
          
          // 读取输出避免缓冲区满
          try (BufferedReader reader = new BufferedReader(new InputStreamReader(packProcess.getInputStream()))) {
              String line;
              while ((line = reader.readLine()) != null) {
                  // 静默处理，避免过多日志
              }
          }
          
          int packExitCode = packProcess.waitFor();
          
          if (packExitCode != 0) {
              System.err.println("警告：重新打包Jar文件失败: " + jarFileName + " (退出码: " + packExitCode + ")");
              return false;
          }
          
          return true;
      }
      
      /**
       * 替换编译后的class文件 - 从独立的编译目录复制新编译的class文件
       */
      private void replaceCompiledClasses() throws IOException {
          System.out.println("替换编译后的class文件");
          
          // 编译输出目录
          File compiledClassesDir = new File(workDir, "compiled_classes");
          
          if (!compiledClassesDir.exists()) {
              System.out.println("没有找到编译输出目录，跳过class文件替换");
              return;
          }
          
          // 确定目标目录
          File targetDir = new File(extractDir, "BOOT-INF/classes");
          if (!targetDir.exists()) {
              targetDir = extractDir; // 普通Jar文件
          }
          
          int replacedCount = 0;
          
          // 递归复制所有编译后的class文件
          replacedCount = copyCompiledClasses(compiledClassesDir, compiledClassesDir, targetDir);
          
          System.out.println("class文件替换完成，共替换 " + replacedCount + " 个文件");
      }
      
      /**
       * 递归复制编译后的class文件
       */
      private int copyCompiledClasses(File sourceDir, File baseDir, File targetDir) throws IOException {
          int count = 0;
          File[] files = sourceDir.listFiles();
          
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      // 递归处理子目录
                      count += copyCompiledClasses(file, baseDir, targetDir);
                  } else if (file.getName().endsWith(".class")) {
                      // 计算相对路径
                      String relativePath = baseDir.toPath().relativize(file.toPath()).toString();
                      File targetFile = new File(targetDir, relativePath);
                      
                      // 确保目标目录存在
                      targetFile.getParentFile().mkdirs();
                      
                      // 复制文件
                      Files.copy(file.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                      System.out.println("已替换: " + relativePath);
                      count++;
                  }
              }
          }
          
          return count;
      }
      
      /**
       * 获取修改过的Java文件列表
       */
      private List<File> getModifiedJavaFiles() {
          // 这里需要实现获取修改过的Java文件的逻辑
          // 目前先返回所有Java文件，但这应该根据实际的修改跟踪来实现
          List<File> javaFiles = new ArrayList<>();
          findJavaFiles(sourceDir, javaFiles);
          return javaFiles;
      }
      
      /**
       * 递归查找Java文件
       */
      private void findJavaFiles(File dir, List<File> javaFiles) {
          File[] files = dir.listFiles();
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      findJavaFiles(file, javaFiles);
                  } else if (file.getName().endsWith(".java")) {
                      javaFiles.add(file);
                  }
              }
          }
      }
      
      /**
       * 删除目录及其所有内容
       */
      private void deleteDirectory(File dir) throws IOException {
          if (dir.exists()) {
              Files.walk(dir.toPath())
                  .sorted((a, b) -> -a.compareTo(b)) // 逆序，先删除文件再删除目录
                  .forEach(path -> {
                      try {
                          Files.delete(path);
                      } catch (IOException e) {
                          System.err.println("删除文件失败: " + path + " - " + e.getMessage());
                      }
                  });
          }
      }
      
      /**
       * 递归添加目录到Jar文件
       */
      private void addDirectoryToJar(File directory, String basePath, JarOutputStream jos) throws IOException {
          File[] files = directory.listFiles();
          if (files != null) {
              for (File file : files) {
                  String entryName = basePath + file.getName();
                  
                  if (file.isDirectory()) {
                      // 添加目录条目
                      if (!entryName.endsWith("/")) {
                          entryName += "/";
                      }
                      JarEntry entry = new JarEntry(entryName);
                      jos.putNextEntry(entry);
                      jos.closeEntry();
                      
                      // 递归添加子目录
                      addDirectoryToJar(file, entryName, jos);
                  } else {
                      // 添加文件
                      JarEntry entry = new JarEntry(entryName);
                      jos.putNextEntry(entry);
                      
                      try (FileInputStream fis = new FileInputStream(file)) {
                          byte[] buffer = new byte[8192];
                          int length;
                          while ((length = fis.read(buffer)) > 0) {
                              jos.write(buffer, 0, length);
                          }
                      }
                      
                      jos.closeEntry();
                  }
              }
          }
      }
      
      /**
       * 查找目录下所有class文件
       */
      private List<File> findClassFiles(File directory) {
          List<File> classFiles = new ArrayList<>();
          findClassFilesRecursive(directory, classFiles);
          return classFiles;
      }
      
      /**
       * 递归查找class文件
       */
      private void findClassFilesRecursive(File directory, List<File> classFiles) {
          File[] files = directory.listFiles();
          if (files != null) {
              for (File file : files) {
                  if (file.isDirectory()) {
                      findClassFilesRecursive(file, classFiles);
                  } else if (file.getName().endsWith(".class")) {
                      classFiles.add(file);
                  }
              }
          }
      }
      
      /**
       * 复制目录
       */
      private void copyDirectory(File source, File target) throws IOException {
          if (!target.exists()) {
              target.mkdirs();
          }
          
          File[] files = source.listFiles();
          if (files != null) {
              for (File file : files) {
                  File targetFile = new File(target, file.getName());
                  
                  if (file.isDirectory()) {
                      copyDirectory(file, targetFile);
                  } else {
                      Files.copy(file.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
                  }
              }
          }
      }
      
      /**
       * 清理工作目录
       */
      public void cleanup() {
          if (workDir != null && workDir.exists()) {
              try {
                  deleteDirectory(workDir);
                  System.out.println("工作目录清理完成");
              } catch (IOException e) {
                  System.err.println("清理工作目录失败: " + e.getMessage());
              }
          }
      }
      
  
      
      /**
       * 获取工作目录
       */
      public File getWorkDir() {
          return workDir;
      }
      
      /**
       * 获取源码目录
       */
      public File getSourceDir() {
          return sourceDir;
      }
      
      /**
       * 检查是否为Spring Boot Jar文件
       */
      private boolean isSpringBootJar(File jarFile) {
          try (JarFile jar = new JarFile(jarFile)) {
              // 检查是否存在Spring Boot特征目录
              return jar.getEntry("BOOT-INF/") != null || 
                     jar.getEntry("META-INF/spring-boot-version") != null ||
                     jar.getEntry("org/springframework/boot/loader/") != null;
          } catch (IOException e) {
              return false;
          }
      }
      
      /**
       * 验证Spring Boot兼容性
       */
      private void validateSpringBootCompatibility(File jarFile) throws IOException {
          System.out.println("验证Spring Boot兼容性...");
          
          try (JarFile jar = new JarFile(jarFile)) {
              // 检查嵌套jar文件是否被正确存储（不压缩）
              Enumeration<JarEntry> entries = jar.entries();
              while (entries.hasMoreElements()) {
                  JarEntry entry = entries.nextElement();
                  if (entry.getName().startsWith("BOOT-INF/lib/") && entry.getName().endsWith(".jar")) {
                      try {
                          // 检查嵌套jar文件的压缩方式
                          if (entry.getMethod() != ZipEntry.STORED) {
                              System.err.println("警告：嵌套jar文件 " + entry.getName() + " 被压缩，可能导致Spring Boot启动失败");
                              System.err.println("建议：使用-M0参数确保嵌套jar文件不压缩");
                          } else {
                              System.out.println("✓ 嵌套jar文件 " + entry.getName() + " 存储方式正确（未压缩）");
                          }
                      } catch (Exception e) {
                          System.err.println("检查嵌套jar文件 " + entry.getName() + " 时出错: " + e.getMessage());
                      }
                  }
              }
              
              // 检查Spring Boot加载器类是否存在
              if (jar.getEntry("org/springframework/boot/loader/JarLauncher.class") == null) {
                  System.err.println("警告：未找到Spring Boot加载器类，可能不是有效的Spring Boot jar");
              } else {
                  System.out.println("✓ Spring Boot加载器类存在");
              }
              
              // 检查MANIFEST.MF中的Main-Class
              JarEntry manifestEntry = (JarEntry) jar.getEntry("META-INF/MANIFEST.MF");
              if (manifestEntry != null) {
                  try (InputStream is = jar.getInputStream(manifestEntry);
                       BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
                      String line;
                      while ((line = reader.readLine()) != null) {
                          if (line.startsWith("Main-Class:")) {
                              String mainClass = line.substring("Main-Class:".length()).trim();
                              if (mainClass.contains("springframework.boot.loader")) {
                                  System.out.println("✓ Spring Boot Main-Class正确: " + mainClass);
                              } else {
                                  System.err.println("警告：Main-Class可能不正确: " + mainClass);
                              }
                              break;
                          }
                      }
                  }
              }
          }
          
          System.out.println("Spring Boot兼容性验证完成");
      }
      
  } 