0

I have a java class SortTest that contains subclasses that implement an interface Sorter. I've been working in Eclipse but I need to compile and run in UNIX so I can pass command line arguments in. So I've been accessing the directory that my .java files are in using

cd Documents/workspace/csc220/src/prog09

then I compile my class and interface using

javac Sorter.java SortTest.java

with no problems. However, when I try to run with

java SortTest 10 //10 is an arbitrary argument

I get this error:

Exception in thread "main" java.lang.NoClassDefFoundError: SortTest/java
Caused by: java.lang.ClassNotFoundException: SortTest.java
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

I have looked at other threads that seem to indicate this may be an issue with compile time/ run time availability of Sorter, but the error mentions only SortTest, which I found confusing. How might I fix this problem? It isn't dependent on my actual code, is it?

EDIT: Here is the code for SortTest.java:

package prog09;
import java.util.Random;

public class SortTest<E extends Comparable<E>> {
  public void test (Sorter<E> sorter, E[] array) {
    E[] copy = array.clone();
    sorter.sort(copy);
    System.out.println(sorter);
    for (int i = 0; i < copy.length; i++)
      System.out.print(copy[i] + " ");
    System.out.println();
  }

  public static void main (String[] args) {
    Integer[] array = { 3, 1, 4, 1, 5, 9, 2, 6 };
    int size = 0;

    try{
        size = Integer.parseInt(args[0]);
    }catch(NumberFormatException e){
        System.out.println("Your argument was not an integer! Quitting program...");
        return;
    }


    if (args.length > 0) {
      // Print out command line argument if there is one.
      System.out.println("args[0] = " + args[0]);

      // Create a random object to call random.nextInt() on.
      Random random = new Random(0);

      // Make array.length equal to args[0] and fill it with random
      // integers:
      for(int i = 0; i < size; i++){
          array[i] = random.nextInt();
      }
    }
    //print out the array if array.length <= 100
    if(array.length <= 100){
        System.out.printf("[ ");
        for(int i = 0; i < array.length; i++){
            System.out.printf(array[i]+" ");
        }
        System.out.printf("]");
    }

    SortTest<Integer> tester = new SortTest<Integer>();
    tester.test(new InsertionSort<Integer>(), array);
     tester.test(new HeapSort<Integer>(), array);
     tester.test(new QuickSort<Integer>(), array);
     tester.test(new MergeSort<Integer>(), array);
  }
}

class InsertionSort<E extends Comparable<E>>
  implements Sorter<E> {
  public void sort (E[] array) {
    for (int n = 0; n < array.length; n++) {
      E data = array[n];
      int i = n;
      // while array[i-1] > data move array[i-1] to array[i] and
      // decrement i
      while(i > 0 && array[i-1].compareTo(data) > 0){
          array[i] = array[i-1];
          i--;
      }
      array[i] = data;
    }
  }
}

class HeapSort<E extends Comparable<E>>
  implements Sorter<E> {

  private E[] array;

  private void swap (int i, int j) {
    E data = array[i];
    array[i] = array[j];
    array[j] = data;
  }

  public void sort (E[] array) {
    this.array = array;

    for (int i = parent(array.length - 1); i >= 0; i--)
      swapDown(i, array.length - 1);

    for (int n = array.length - 1; n >= 0; n--) {
      swap(0, n);
      swapDown(0, n - 1);
    }
  }

  public void swapDown (int root, int end) {
    // Calculate the left child of root.
    int leftChild = 2*root + 1;
    // while the left child is still in the array
    //   calculate the right child
    //   if the right child is in the array and 
    //      it is bigger than than the left child
    //     bigger child is right child
    //   else
    //     bigger child is left child
    //   if the root is not less than the bigger child
    //     return
    //   swap the root with the bigger child
    //   update root and calculate left child
    while(leftChild < end){
        int rightChild = 2*root + 2;
        int bigChild;
        if(rightChild < end && array[rightChild].compareTo(array[leftChild]) > 0){
            bigChild = rightChild;
        }else{
            bigChild = leftChild;
        }
        if(!(array[root].compareTo(array[bigChild]) < 0)){
            return;
        }
        swap(root, bigChild);
        root = bigChild;
        leftChild = 2*root + 1;
    }
  }

  private int left (int i) { return 2 * i + 1; }
  private int right (int i) { return 2 * i + 2; }
  private int parent (int i) { return (i - 1) / 2; }
}

class QuickSort<E extends Comparable<E>>
  implements Sorter<E> {

  private E[] array;
  private void swap (int i, int j) {
    E data = array[i];
    array[i] = array[j];
    array[j] = data;
  }

  public void sort (E[] array) {
    this.array = array;
    sort(0, array.length-1);
  }

  private void sort(int left, int right) {
    if (left >= right)
      return;

    swap(left, (left + right) / 2);

    E pivot = array[left];
    int a = left + 1;
    int b = right;
    while (a <= b) {
      // Move a forward if array[a] <= pivot
        if(!(array[a].compareTo(pivot) > 0)){
            a++;
        }else
      // Move b backward if array[b] > pivot
        if(array[b].compareTo(pivot) > 0){
            b--;
        }else
      // Otherwise swap array[a] and array[b]
        swap(a,b);

    }

    swap(left, b);

    sort(left, b-1);
    sort(b+1, right);
  }
}

class MergeSort<E extends Comparable<E>>
  implements Sorter<E> {

  private E[] array, array2;

  public void sort (E[] array) {
    this.array = array;
    array2 = array.clone();
    sort(0, array.length-1);
  }

  private void sort(int left, int right) {
    if (left >= right)
      return;

    int middle = (left + right) / 2;
    sort(left, middle);
    sort(middle+1, right);

    int i = left;
    int a = left;
    int b = middle+1;
    while (a <= middle || b <= right) {
      // If both a <= middle and b <= right
      // copy the smaller of array[a] or array[b] to array2[i]
      // Otherwise just copy the remaining elements to array2
        if(a <= middle && b <= right){
            if(array[a].compareTo(array[b]) < 0){
                array2[i] = array[a];
                a++;
            }else{
                array2[i] = array[b];
                b++;
            }
            i++;
        }else{
            if(a > middle)
                System.arraycopy(array, b, array2, i, array.length-b-1);
            else
                System.arraycopy(array, a, array2, i, middle-a+1);
            break;
        }
    }

    System.arraycopy(array2, left, array, left, right - left + 1);
  }
}

Here is Sorter.java:

package prog09;

public interface Sorter<E extends Comparable<E>> {
    void sort (E[] array);
}

And here is the error message I get when I run java -cp prog09 SortTest from the parent directory:

Exception in thread "main" java.lang.NoClassDefFoundError: SortTest (wrong name: prog09/SortTest)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
user2871915
  • 469
  • 7
  • 17
  • 11
    you're sure you're running `java SortTest` and not `java SortTest.java` ? – DHall Nov 03 '13 at 17:49
  • the compiler is producing a `SortTest.class` file? and you are in the same directory as it? – vandale Nov 03 '13 at 17:53
  • Unix hasn't been available for 10 years. What Linux distribution are you using? And why aren't you using ant or Maven? – bmargulies Nov 03 '13 at 17:53
  • 1
    @bmargulies: one has to start something. Using Ant or (gasp) Maven without clearly understanding packages, source files, class files and the classpath is not a good idea. I would rather applaud someone who starts to compile and run classes from the sommand line rather than doing everything with an IDE without understanding anything. – JB Nizet Nov 03 '13 at 17:56
  • Yes, I am running java SortTest and not java SortTest.java. I'm using Terminal on a Mac. I'm a student, and not yet very experienced in Linux, so Ant and Maven is a bit beyond my scope as of now. – user2871915 Nov 03 '13 at 17:58
  • That's not what the error message says. Maybe you have a strange shell that autocompletes file names. Try going to the parent directory, and launching `java -cp prog09 SortTest`. – JB Nizet Nov 03 '13 at 18:00
  • Is it possible that you could provide us with your actual code so that we can compile and test it> – aa8y Nov 03 '13 at 18:27
  • Ended up with a very similar error when I tried that. – user2871915 Nov 03 '13 at 18:30
  • Sigh. And what's the complete stack trace of this very similar error? If you don't provide any information, we can't help you. We can't read your screen. – JB Nizet Nov 03 '13 at 18:33
  • Sorry. I added the code in my .java files as well as the error I get when I run the command in the parent directory. – user2871915 Nov 03 '13 at 19:43
  • possible duplicate of [Why it could not find the main class?](http://stackoverflow.com/questions/2416750/why-it-could-not-find-the-main-class) – Philipp Wendler Mar 15 '14 at 09:52

1 Answers1

1
  1. Ensure both Sorter and SortTest source files are in the default package space (i.e. no package prog9 statements in the code.
  2. Assuming SortTest has the main, verify ls -l SortTest.class is in the current directory.
  3. Verify that the java command is running /usr/bin/java (you say you're on a Mac and darwin has a slightly complex JAVA_HOME management environment) and not some other thing.
  4. Run java -classpath . SortTest and tell us what happens.

The OP put both files into the default namespace by removing package prog09 and it "worked."

From the command line, leaving the package prog09 in place, one could do this:

mkdir prog09
javac Sorter.java SortTest.java
mv Sorter.class SortTest.class prog09
java -classpath . prog09.SortTest
Buzz Moschetti
  • 7,057
  • 3
  • 23
  • 33
  • Commenting out the package prog09 statements seems to have done the trick. Thanks! Would you mind explaining why exactly this happens? I'm pretty new to this sort of thing so I'd like to learn. – user2871915 Nov 03 '13 at 19:59
  • Package naming, classpaths, and the ability for one class to reference other classes without explicit import are all related. I recommend reading http://docs.oracle.com/javase/tutorial/java/package/packages.html – Buzz Moschetti Nov 03 '13 at 21:28