Java Exporting as Jar has errors [closed]

2020-05-10 12:51发布

问题:

Two questions

1) When exporting a java project as a JAR file, how does the application know which Class in the package to run first? My applicatino specifically requires that the userInterface.java file run before the CommonDenom.java file.

2) When running the java file I'm getting an error that says "The Java JAR file "commonDenom.jar" could not be launched. Check the Console for possible messages."

Where do I start to figure this out? I checked the console but it doesn't seem to be registering anything at the time the error message pops.

package commonDenom;

import java.util.Arrays;
import java.util.Scanner;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;


public class UserInterface {
    Shell shell;
    Button btnNext;
    Button btnDone;
    Text input;
    Text output;
    static int count;
    static int[] finalNums;
    int[] nums = new int[1000];

    public static void main(String[] args){
        Display display = new Display();
        new UserInterface(display);
        display.dispose();
    }

    public UserInterface(Display display){
        shell = new Shell(display);
        shell.setSize(220,350);
        shell.open();

        input = new Text(shell, SWT.SINGLE);
        input.setBounds(10, 10, 100, 20);

        btnNext = new Button(shell, SWT.PUSH);
        btnNext.setBounds(10, 40, 100, 30);
        btnNext.setText("Next");
        nextPress();

        btnDone = new Button(shell, SWT.PUSH);
        btnDone.setBounds(10, 80, 100, 30);
        btnDone.setText("Done");
        donePress();

        output = new Text(shell, SWT.SINGLE);
        output.setBounds(10, 120, 200, 200);

        while(!shell.isDisposed()){
            if(!display.readAndDispatch()){
                display.sleep();
            }
        }
    }

    public void nextPress(){

        btnNext.addSelectionListener(new SelectionAdapter(){
            int x = 0;
            @Override
            public void widgetSelected(SelectionEvent e) {
                    nums[x] = Integer.parseInt(input.getText());
                    System.out.println("nums[" + x + "]:" + nums[x]);
                    x++;
                    count++;
            }
        });
    }

    public void donePress(){
        btnDone.addSelectionListener(new SelectionAdapter(){
            @Override
            public void widgetSelected(SelectionEvent e) {
                finalNums = new int[count]; 
                for(int i = 0; i < count; i++){
                    finalNums[i] = nums[i];
                }
                System.out.println("finalNums:" + Arrays.toString(finalNums));
                commonDenom.compare();
                if(commonDenom.getResult() == 0){
                    output.setText(Arrays.toString(finalNums) + "\nThese numbers do not have a \ncommon multiplier");
                }
                else{
                    output.setText(Arrays.toString(finalNums) + "\nResult:" + String.valueOf(commonDenom.getResult()));
                }
            }
        });
    }
    public static int[] getNums(){
        return finalNums;
    }
}

Manifest.txt location: /Dropbox/workspace/commonDenom/bin

Class location: /Dropbox/workspace/commonDenom/bin/commonDenom/

Class names:

commonDenom.class
UserInterface.class
UserInterface$1.class (I didn't create this)
UserInterface$2.class (I didn't create this)

Manifest.txt content (with two trailing blank lines):

Main-Class: commonDenom.UserInterface

jar tf CommonDenom.jar returns the following:

META-INF/
META-INF/MANIFEST.MF
Manifest.txt
commonDenom/
commonDenom/commonDenom.class
commonDenom/UserInterface$1.class
commonDenom/UserInterface$2.class
commonDenom/UserInterface.class

回答1:

I recommend to create the jar by hand first. It will be a good sanity test, and you will learn what it takes to do it. Here are the steps:

  1. Create a Manifest.txt file somewhere, let's say your project root. One line is enough, like this:

    Main-Class: commonDenom.UserInterface
    

    Make sure the file ends with a newline. Eclipse doesn't put a newline at the end of the file by default. It's ok to have trailing blank lines.

  2. Go to the parent directory where Eclipse puts your class files. For example in a Maven project this is target/classes relative from the project root. Ant builds might use bin instead. In your example this should be the directory that contains commonDenom (which in turn contains the build product: UserInterface.class)

  3. Create the jar:

    jar cfm /tmp/somename.jar /path/to/Manifest.txt commonDenom
    # or probably:
    jar cfm /tmp/somename.jar /path/to/Manifest.txt *
    

    This will put your tree of class files into the jar with the specified manifest file.

Now you should be able to run this file. This can be your baseline test.

You can check the content of the jar with the command:

jar tf /tmp/somename.jar

It should print something like:

META-INF/
META-INF/MANIFEST.MF
commonDenom/UserInterface.class
...  # your other class files...

Now that you have your baseline test, you can try to create the jar using Eclipse. If the jar created by Eclipse doesn't work, you can look at its content to see the differences from your baseline case, which should help you debug the problem.



回答2:

You can define an entry point of your application in the MANIFEST file. Have a look here: http://docs.oracle.com/javase/tutorial/deployment/jar/appman.html