Search code examples
javaclassloaderexecutable-jar.class-file

Java code equivelent of jar cf


I am writing a java program that takes my generated .class files and Jars them then loads them into memory using a class loader.

I currently have a working jarring system with the code:

 public static int BUFFER_SIZE = 10240;
  protected static void createJarArchive(File archiveFile, File[] tobeJared) {
    try {
      byte buffer[] = new byte[BUFFER_SIZE];
      // Open archive file
      FileOutputStream stream = new FileOutputStream(archiveFile);
      JarOutputStream out = new JarOutputStream(stream, new Manifest());

      for (int i = 0; i < tobeJared.length; i++) {
        if (tobeJared[i] == null || !tobeJared[i].exists()
            || tobeJared[i].isDirectory())
          continue; // Just in case...
        System.out.println("Adding " + tobeJared[i].getName());

        // Add archive entry
        JarEntry jarAdd = new JarEntry(getPackageNameModified +tobeJared[i].getName());
        jarAdd.setTime(tobeJared[i].lastModified());
        out.putNextEntry(jarAdd);

        // Write file to archive
        FileInputStream in = new FileInputStream(tobeJared[i]);
        while (true) {
          int nRead = in.read(buffer, 0, buffer.length);
          if (nRead <= 0)
            break;
          out.write(buffer, 0, nRead);
        }
        in.close();
      }

      out.close();
      stream.close();
      System.out.println("Adding completed OK");
    } catch (Exception ex) {
      ex.printStackTrace();
      System.out.println("Error: " + ex.getMessage());
    }
  }

Reference to something in code:

getPackageNameModified = com\Test

However, when I go to load the jar into memory I get a error of:

Could not load jar C:\Users\Dalton\AppData\Local\Temp\Test.jar into JVM. (Could not find class com.Test.ObjectFactory.)

I am using a squoop class loader to do this.

AKA:

ClassLoaderStack.addJarFile(jarFileAbsolute, absoluteClass);

Using the following command line the class loader code works properly, but I want to avoid command line in a java program:

jar cf C:\Users\Dalton\AppData\Local\Temp\Test.jar -C C:\Users\Dalton\AppData\Local\Temp\Test\com.Test com\Test

Solution

  • The following fixed my issue:

    try
        {
            byte buffer[] = new byte[BUFFER_SIZE];
            // Open archive file
            FileOutputStream stream = new FileOutputStream(archiveFile);
            JarOutputStream out = new JarOutputStream(stream, new Manifest());
    
            for (int i = 0; i < tobeJared.length; i++)
            {
                if (tobeJared[i].toString().endsWith(CLASS))
                { 
                    // the .replace \\ with / is a java JDK bug that requires all
                        // paths to use / and end in / for a jar to properly be made
    
                    LOG.info("Adding "
                            + getPackageNameModified().replace(
                                    DOUBLE_BACKSLASH, FORWARD_SLASH) + FORWARD_SLASH + tobeJared[i].getName()
                            + " to the temporary JAR.");
    
                    // Add archive entry
                    JarEntry jarAdd = new JarEntry(
                            getPackageNameModified().replace(DOUBLE_BACKSLASH,
                                    FORWARD_SLASH) + FORWARD_SLASH + tobeJared[i].getName());
                    jarAdd.setTime(tobeJared[i].lastModified());
                    out.putNextEntry(jarAdd);
    
                    // Write file to archive
                    FileInputStream in = new FileInputStream(tobeJared[i]);
                    while (true)
                    {
                        int nRead = in.read(buffer, 0, buffer.length);
                        if (nRead <= 0) break;
                        out.write(buffer, 0, nRead);
                    }
                    in.close();
                }
            }
    
            out.close();
            stream.close();
            LOG.info("Adding complete --> Success");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
            LOG.error("Error: " + ex.getMessage());
        }
    

    Issue is in java the \ is a bug. All directory splits use a / instead, and end in /. I do not know why this is the issue, but because of it the generated JAR can class load.