Rectangle 27 701

Reasons why Java cannot find the class

First of all, you need to understand the correct way to launch a program using the java (or javaw) command.

java [ <option> ... ] <class-name> [<argument> ...]
<option>

where <option> is a command line option (starting with a "-" character), <class-name> is a fully qualified Java class name, and <argument> is an arbitrary command line argument that gets passed to your application.

<class-name>

What this is going to do is the following:

<argument>

The fully qualified name (FQN) for the class is conventionally written as you would in Java source code; e.g.

packagename.packagename2.packagename3.ClassName

However some versions of the java command allow you to use slashes instead of periods; e.g.

packagename/packagename2/packagename3/ClassName

which (confusingly) looks like a file pathname, but isn't one. Note that the term fully qualified name is standard Java terminology ... not something I just made up to confuse you :-)

Here is an example of what a java command should look like:

So why might it be unable to find the class? Basically, there are two main causes:

java -Xmx100m com.acme.example.ListUsers fred joe bert

The above is going to cause the java command to do the following:

  • Search for the compiled version of the com.acme.example.ListUsers class.
  • Check that the class has a main method with signature, return type and modifiers given by public static void main(String[]). (Note, the method argument's name is NOT part of the signature.)
  • Call that method passing it the command line arguments ("fred", "joe", "bert") as a String[].

When you get the message "Could not find or load main class ...", that means that the first step has failed. The java command was not able to find the class. And indeed, the "..." in the message will be the fully qualified class name that java is looking for.

The first likely cause is that you may have provided the wrong class name. (Or ... the right class name, but in the wrong form.) Considering the example above, here a variety of wrong ways to specify the class name:

Example #1 - a simple class name:

java ListUser

When the class is declared in a package such as com.acme.example, then you must use the full classname including the package name in the java command; e.g.

java com.acme.example.ListUser

Example #2 - a filename or pathname rather than a class name:

java ListUser.class
java com/acme/example/ListUser.class

Example #3 - a class name with the casing incorrect:

java com.acme.example.listuser
  • Example #4 - a typo java com.acme.example.mistuser

Example #5 - a source filename

/usr/local/acme/classes/com/acme/example/Foon.class
java ListUser.java

Example #6 - you forgot the class name entirely

java lots of arguments

The second likely cause is that the class name is correct, but that the java command cannot find the class. To understand this, you need to understand the concept of the "classpath". This is explained well by the Oracle documentation:

java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
java
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

So ... if you have specified the class name correctly, the next thing to check is that you have specified the classpath correctly:

  • Read the three documents linked above. (Yes ... READ them. It is important that a Java programmer understands at least the basics of how the Java classpath mechanisms works.)
  • Look at command line and / or the CLASSPATH environment variable that is in effect when you run the java command. Check that the directory names and JAR file names are correct.
  • If there are relative pathnames in the classpath, check that they resolve correctly ... from the current directory that is in effect when you run the java command.

Please feel free to add comments suggesting improvements or corrections.

  • Check that the class (mentioned in the error message) can be located on the effective classpath.
  • Note that the classpath syntax is different for Windows versus Linux and Mac OS.

The thing which helped me to identify the problem is: "Yes ... READ them" comment :)

When you put a directory on the classpath, it notionally corresponds to the root of the qualified name space. Classes are located in the directory structure beneath that root, by mapping the fully qualified name to a pathname. So for example, if "/usr/local/acme/classes" is on the class path, then when the JVM looks for a class called com.acme.example.Foon, it will look for a ".class" file with this pathname:

/usr/local/acme/classes/com/acme/example/Foon.class

You should explain directory structure and the proper directory to be in to run java programs. One of the most confusing things for me and I'm sure other newbie Java developers is the weird folder structure.

If you had put "/usr/local/acme/classes/com/acme/example" on the classpath, then the JVM wouldn't be able to find the class.

If your classes FQN is com.acme.example.Foon, then the JVM is going to look for "Foon.class" in the directory "com/acme/example":

To give a concrete example, supposing that:

com.acme.example.Foon
/usr/local/acme/classes/com/acme/example/
# wrong, FQN is needed
java Foon

# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon

# wrong, similar to above
java -classpath . com.acme.example.Foon

# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon

# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon
  • The -classpath option can be shortened to -cp in most Java releases. Check the respective manual entries for java, javac and so on.
  • Think carefully when choosing between absolute and relative pathnames in classpaths. Remember that a relative pathname may "break" if the current directory changes.

The classpath needs to include all of the other (non-system) classes that your application depends on. (The system classes are located automatically, and you rarely need to concern yourself with this.) For the main class to load correctly, the JVM needs to find:

  • all classes and interfaces that are referred to by means of variable or variable declarations, or method call or field access expressions.

(Note: the JLS and JVM specifications allow some scope for a JVM to load classes "lazily", and this can affect when a classloader exception is thrown.)

It occasionally happens that someone puts a source code file into the the wrong folder in their source code tree, or they leave out the package declaration. If you do this in an IDE, the IDE's compiler will tell you about this immediately. Similarly if you use a decent Java build tool, the tool will run javac in a way that will detect the problem. However, if you build your Java code by hand, you can do it in such a way that the compiler doesn't notice the problem, and the resulting ".class" file is not in the place that you expect it to be.

The alternative syntax used for "executable" JAR files is as follows:

java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

In this case the name of the entry-point class (i.e. com.acme.example.ListUser) and the classpath are specified in the MANIFEST of the JAR file.

A typical Java IDE has support for running Java applications in the IDE JVM itself or in a child JVM. These are generally immune from this particular exception, because the IDE uses its own mechanisms to construct the runtime classpath, identify the main class and create the java command line.

However it is still possible for this exception to occur, if you do things behind the back of the IDE. For example, if you have previously set up an Application Launcher for your Java app in Eclipse, and you then moved the JAR file containing the "main" class to a different place in the file system without telling Eclipse, Eclipse would unwittingly launch the JVM with an incorrect classpath.

In short, if you get this problem in an IDE, check for things like stale IDE state, broken project references or broken launcher configurations.

It is also possible for an IDE to simply get confused. IDE's are hugely complicated pieces of software comprising many interacting parts. Many of these parts adopt various caching strategies in order to make the IDE as a whole responsive. These can sometimes go wrong, and one possible symptom is problems when launching applications. If you suspect this could be happening, it is worth restarting your IDE.

I had this problem when I was trying to run a Class with a 3rd party library. I invoked java like this: java -cp ../third-party-library.jar com.my.package.MyClass; this does not work, instead it is necessary to add the local folder to the class path as well (separated by :, like this: java -cp ../third-party-library.jar:. com.my.package.MyClass, then it should work

After years of java programming I still managed to end up on this page. For me the issue was that the classpath syntax is OS-dependent. I'm kind of new to programming on Windows and had no idea.

Additional notes, point 2 save me! It is sad to see that java does not say it does not find an imported class, but instead the main class you're trying to run. This is misleading, although I'm sure there's a reason for that. I had the case where java knew exactly where my class is, however it couldn't find one of the imported classes. Instead of saying that, it complained about not finding my main class. Really, annoing.

@StephenC Great answer. Consider adding to your answer the suggestion to re-run the failing java.exe invocations with the -Xdiag flag for JDK versions >7. This tip is in the answer stackoverflow.com/a/39117892/110126.

java - What does "Could not find or load main class" mean? - Stack Ove...

java class main
Rectangle 27 662

Reasons why Java cannot find the class

First of all, you need to understand the correct way to launch a program using the java (or javaw) command.

java [ <option> ... ] <class-name> [<argument> ...]
<option>
<class-name>
<argument>

The fully qualified name (FQN) for the class is conventionally written as you would in Java source code; e.g.

packagename.packagename2.packagename3.ClassName

However some versions of the java command allow you to use slashes instead of periods; e.g.

packagename/packagename2/packagename3/ClassName

which (confusingly) looks like a file pathname, but isn't one. Note that the term fully qualified name is standard Java terminology ... not something I just made up to confuse you :-)

Here is an example of what a java command should look like:

java -Xmx100m com.acme.example.ListUsers fred joe bert

The above is going to cause the java command to do the following:

  • Search for the compiled version of the com.acme.example.ListUsers class.
  • Check that the class has a main method with signature, return type and modifiers given by public static void main(String[]). (Note, the method argument's name is NOT part of the signature.)
  • Call that method passing it the command line arguments ("fred", "joe", "bert") as a String[].

When you get the message "Could not find or load main class ...", that means that the first step has failed. The java command was not able to find the class. And indeed, the "..." in the message will be the fully qualified class name that java is looking for.

The first likely cause is that you may have provided the wrong class name. (Or ... the right class name, but in the wrong form.) Considering the example above, here a variety of wrong ways to specify the class name:

Example #1 - a simple class name:

java ListUser

When the class is declared in a package such as com.acme.example, then you must use the full classname including the package name in the java command; e.g.

java com.acme.example.ListUser

Example #2 - a filename or pathname rather than a class name:

java ListUser.class
java com/acme/example/ListUser.class

Example #3 - a class name with the casing incorrect:

java com.acme.example.listuser
  • Example #4 - a typo java com.acme.example.mistuser

Example #5 - a source filename

java ListUser.java

Example #6 - you forgot the class name entirely

java lots of arguments

The second likely cause is that the class name is correct, but that the java command cannot find the class. To understand this, you need to understand the concept of the "classpath". This is explained well by the Oracle documentation:

java

So ... if you have specified the class name correctly, the next thing to check is that you have specified the classpath correctly:

  • Read the three documents linked above. (Yes ... READ them. It is important that a Java programmer understands at least the basics of how the Java classpath mechanisms works.)
  • Look at command line and / or the CLASSPATH environment variable that is in effect when you run the java command. Check that the directory names and JAR file names are correct.
  • If there are relative pathnames in the classpath, check that they resolve correctly ... from the current directory that is in effect when you run the java command.
  • Check that the class (mentioned in the error message) can be located on the effective classpath.
  • Note that the classpath syntax is different for Windows versus Linux and Mac OS.

When you put a directory on the classpath, it notionally corresponds to the root of the qualified name space. Classes are located in the directory structure beneath that root, by mapping the fully qualified name to a pathname. So for example, if "/usr/local/acme/classes" is on the class path, then when the JVM looks for a class called com.acme.example.Foon, it will look for a ".class" file with this pathname:

/usr/local/acme/classes/com/acme/example/Foon.class

If you had put "/usr/local/acme/classes/com/acme/example" on the classpath, then the JVM wouldn't be able to find the class.

If your classes FQN is com.acme.example.Foon, then the JVM is going to look for "Foon.class" in the directory "com/acme/example":

To give a concrete example, supposing that:

com.acme.example.Foon
/usr/local/acme/classes/com/acme/example/
# wrong, FQN is needed
java Foon

# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon

# wrong, similar to above
java -classpath . com.acme.example.Foon

# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon

# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon
  • The -classpath option can be shortened to -cp in most Java releases. Check the respective manual entries for java, javac and so on.
  • Think carefully when choosing between absolute and relative pathnames in classpaths. Remember that a relative pathname may "break" if the current directory changes.

The classpath needs to include all of the other (non-system) classes that your application depends on. (The system classes are located automatically, and you rarely need to concern yourself with this.) For the main class to load correctly, the JVM needs to find:

  • all classes and interfaces that are referred to by means of variable or variable declarations, or method call or field access expressions.

(Note: the JLS and JVM specifications allow some scope for a JVM to load classes "lazily", and this can affect when a classloader exception is thrown.)

It occasionally happens that someone puts a source code file into the the wrong folder in their source code tree, or they leave out the package declaration. If you do this in an IDE, the IDE's compiler will tell you about this immediately. Similarly if you use a decent Java build tool, the tool will run javac in a way that will detect the problem. However, if you build your Java code by hand, you can do it in such a way that the compiler doesn't notice the problem, and the resulting ".class" file is not in the place that you expect it to be.

The alternative syntax used for "executable" JAR files is as follows:

java [ <option> ... ] -jar <jar-file-name> [<argument> ...]
java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

In this case the name of the entry-point class (i.e. com.acme.example.ListUser) and the classpath are specified in the MANIFEST of the JAR file.

A typical Java IDE has support for running Java applications in the IDE JVM itself or in a child JVM. These are generally immune from this particular exception, because the IDE uses its own mechanisms to construct the runtime classpath, identify the main class and create the java command line.

However it is still possible for this exception to occur, if you do things behind the back of the IDE. For example, if you have previously set up an Application Launcher for your Java app in Eclipse, and you then moved the JAR file containing the "main" class to a different place in the file system without telling Eclipse, Eclipse would unwittingly launch the JVM with an incorrect classpath.

In short, if you get this problem in an IDE, check for things like stale IDE state, broken project references or broken launcher configurations.

It is also possible for an IDE to simply get confused. IDE's are hugely complicated pieces of software comprising many interacting parts. Many of these parts adopt various caching strategies in order to make the IDE as a whole responsive. These can sometimes go wrong, and one possible symptom is problems when launching applications. If you suspect this could be happening, it is worth restarting your IDE.

I had this problem when I was trying to run a Class with a 3rd party library. I invoked java like this: java -cp ../third-party-library.jar com.my.package.MyClass; this does not work, instead it is necessary to add the local folder to the class path as well (separated by :, like this: java -cp ../third-party-library.jar:. com.my.package.MyClass, then it should work

After years of java programming I still managed to end up on this page. For me the issue was that the classpath syntax is OS-dependent. I'm kind of new to programming on Windows and had no idea.

Additional notes, point 2 save me! It is sad to see that java does not say it does not find an imported class, but instead the main class you're trying to run. This is misleading, although I'm sure there's a reason for that. I had the case where java knew exactly where my class is, however it couldn't find one of the imported classes. Instead of saying that, it complained about not finding my main class. Really, annoing.

@StephenC Great answer. Consider adding to your answer the suggestion to re-run the failing java.exe invocations with the -Xdiag flag for JDK versions >7. This tip is in the answer stackoverflow.com/a/39117892/110126.

java - What does "Could not find or load main class" mean? - Stack Ove...

java class main
Rectangle 27 18

What is reason of NoClassDefFoundError in Java?

NoClassDefFoundError in Java comes when Java Virtual Machine is not able to find a particular class at runtime which was available during compile time. For example if we have a method call from a class or accessing any static member of a Class and that class is not available during run-time then JVM will throw NoClassDefFoundError. Its important to understand that this is different than ClassNotFoundException which comes while trying to load a class at run-time only and name was provided during runtime not on compile time. Many Java developer mingle this two Error and gets confused.

In short NoClassDefFoundError will come if a class was present during compile time but not available in java classpath during runtime. Normally you will see below line in log when you get NoClassDefFoundError:

NoClassDefFoundError
  • Class is not available in Java Classpath.
  • You might be running your program using jar command and class was not defined in manifest file's ClassPath attribute.
  • Because NoClassDefFoundError is a sub class of java.lang.LinkageError it can also come if one of it dependency like native library may not available.
  • Check for java.lang.ExceptionInInitializerError in your log file. NoClassDefFoundError due to failure of static initialization is quite common.
  • If you are working in J2EE environment than visibility of Class among multiple Classloaders can also cause java.lang.NoClassDefFoundError, see examples and scenario section for detailed discussion.

Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why its there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.

java.lang.NoClassDefFoundError: Could not initialize class com.google....

java noclassdeffounderror
Rectangle 27 68

/**
 * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
 *
 * @param packageName The base package
 * @return The classes
 * @throws ClassNotFoundException
 * @throws IOException
 */
private static Class[] getClasses(String packageName)
        throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    List<File> dirs = new ArrayList<File>();
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        dirs.add(new File(resource.getFile()));
    }
    ArrayList<Class> classes = new ArrayList<Class>();
    for (File directory : dirs) {
        classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
}

/**
 * Recursive method used to find all classes in a given directory and subdirs.
 *
 * @param directory   The base directory
 * @param packageName The package name for classes found inside the base directory
 * @return The classes
 * @throws ClassNotFoundException
 */
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
    List<Class> classes = new ArrayList<Class>();
    if (!directory.exists()) {
        return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
        } else if (file.getName().endsWith(".class")) {
            classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
        }
    }
    return classes;
}

I had a problem with this if my path included spaces. The URL class was escaping spaces to %20, but the new File() constructor treated that as a literal percent sign two zero. I fixed it by changing the dirs.add(...) line to this: dirs.add(new File(resource.toURI())); This also meant I had to add URISyntaxException to the throws clause of getClasses

This also doesn't work if the classes are inside of a Jar.

+1 because this solution does NOT require external libraries... NEVER, really NEVER couple your code randomly with libraries just to achieve one small thing like this. do you know that you are adding potential attack surface for attackers? Nov 2015 an Apache Commons problem discovered that leads to Remote Command Execution just by having Apache Commons in the classpath of an app deployed on Jboss/Weblogic [foxglovesecurity.com/2015/11/06/

@Qix correctly noted that this code does not support jar. In order to support jars & directories. The code was changed as noted below:

java - Can you find all classes in a package using reflection? - Stack...

java reflection packages
Rectangle 27 67

/**
 * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
 *
 * @param packageName The base package
 * @return The classes
 * @throws ClassNotFoundException
 * @throws IOException
 */
private static Class[] getClasses(String packageName)
        throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    List<File> dirs = new ArrayList<File>();
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        dirs.add(new File(resource.getFile()));
    }
    ArrayList<Class> classes = new ArrayList<Class>();
    for (File directory : dirs) {
        classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
}

/**
 * Recursive method used to find all classes in a given directory and subdirs.
 *
 * @param directory   The base directory
 * @param packageName The package name for classes found inside the base directory
 * @return The classes
 * @throws ClassNotFoundException
 */
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
    List<Class> classes = new ArrayList<Class>();
    if (!directory.exists()) {
        return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
        } else if (file.getName().endsWith(".class")) {
            classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
        }
    }
    return classes;
}

I had a problem with this if my path included spaces. The URL class was escaping spaces to %20, but the new File() constructor treated that as a literal percent sign two zero. I fixed it by changing the dirs.add(...) line to this: dirs.add(new File(resource.toURI())); This also meant I had to add URISyntaxException to the throws clause of getClasses

This also doesn't work if the classes are inside of a Jar.

+1 because this solution does NOT require external libraries... NEVER, really NEVER couple your code randomly with libraries just to achieve one small thing like this. do you know that you are adding potential attack surface for attackers? Nov 2015 an Apache Commons problem discovered that leads to Remote Command Execution just by having Apache Commons in the classpath of an app deployed on Jboss/Weblogic [foxglovesecurity.com/2015/11/06/

@Qix correctly noted that this code does not support jar. In order to support jars & directories. The code was changed as noted below:

java - Can you find all classes in a package using reflection? - Stack...

java reflection packages
Rectangle 27 44

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

Update: I just found a really neat way to specify the Application's entry point in eclipse. When you say Export,

Select Jar and next 

[ give it a name in the next window ] and next

and next again

and you'll see " Select the class of the application entry point".

Just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

java - Can't execute jar- file: "no main manifest attribute" - Stack O...

java jar manifest main
Rectangle 27 44

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

Update: I just found a really neat way to specify the Application's entry point in eclipse. When you say Export,

Select Jar and next 

[ give it a name in the next window ] and next

and next again

and you'll see " Select the class of the application entry point".

Just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

java - Can't execute jar- file: "no main manifest attribute" - Stack O...

java jar manifest main
Rectangle 27 44

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

Update: I just found a really neat way to specify the Application's entry point in eclipse. When you say Export,

Select Jar and next 

[ give it a name in the next window ] and next

and next again

and you'll see " Select the class of the application entry point".

Just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

java - Can't execute jar- file: "no main manifest attribute" - Stack O...

java jar manifest main
Rectangle 27 44

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

Update: I just found a really neat way to specify the Application's entry point in eclipse. When you say Export,

Select Jar and next 

[ give it a name in the next window ] and next

and next again

and you'll see " Select the class of the application entry point".

Just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

java - Can't execute jar- file: "no main manifest attribute" - Stack O...

java jar manifest main
Rectangle 27 44

That is because Java cannot find the Main attribute in the MANIFEST.MF file. The Main attribute is necessary to tell java which class it should use as the application's entry point. Inside the jar file, the MANIFEST.MF file is located in META-INF folder. Wondering how you could look at what's inside a jar file? Open the jar file with WinRAR.

The main attribute inside the MANIFEST.MF looks like this:

Main-Class: <packagename>.<classname>

You get this "no main manifest attribute" error when this line is missing from the MANIFEST.MF file.

Update: I just found a really neat way to specify the Application's entry point in eclipse. When you say Export,

Select Jar and next 

[ give it a name in the next window ] and next

and next again

and you'll see " Select the class of the application entry point".

Just pick a class and Eclipse will automatically build a cool MANIFEST.MF for you.

java - Can't execute jar- file: "no main manifest attribute" - Stack O...

java jar manifest main
Rectangle 27 245

1. What does a "Cannot find symbol" error mean?

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

Your Java source code consists of the following things:

true
false
class
while
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
Reader
toString
processEquibalancedElephants
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
  • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
  • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
  • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
  • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
  • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.
  • Perhaps you forgot a new as in: String s = String(); // should be 'new String()'
  • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
  • Perhaps you are shadowing a static or instance variable.
  • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
  • Perhaps you are using (compiling against) the wrong version of an API.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnoord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon before the {. The Java language defines that to be an empty statement. So that code actually means this:

for (int i = 0; i < 100; i++); 

{
    System.out.println("i is " + i);
}

The { ... } block is NOT the body of the for loop, so the declaration of i is not in scope in the the block.

Here is another example of "Cannot find symbol" error that is caused by a typo.

int tmp = ...
int res = tmp(a + b);

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

for
for (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!

The point is that you need to understand what your code is trying to do in order to find the right fix.

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

You are looking at the wrong source code: It often happens that a new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like ...

IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

String s = ...
String s1 = s.substring(1);

It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

Lesson: Don't define your own classes with the same names as common library classes!

Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.

I had another situation where this compilation error occured while eclipse didn't see the problem: Two classes with dependencies defined in the respectively other class. In my case I had an enum, implementing an interface, defined in a class where I foolishly already used the enum.

Somewhat similarly to the comment above, when I compile and run my program from Eclipse it works no problem. Compiling it from the console raises a bunch of these "Cannot find symbol" errors often related to last element in an import. I have no idea what is causing this as there is nothing wrong in the code really.

Another common one I don't see listed (maybe I'm just missing it in the list) is a method named without () after it like String s = ""; int len = s.length;

java - What does a "Cannot find symbol" compilation error mean? - Stac...

java compiler-errors cannot-find-symbol
Rectangle 27 235

1. What does a "Cannot find symbol" error mean?

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

Your Java source code consists of the following things:

true
false
class
while
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
Reader
toString
processEquibalancedElephants
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
  • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
  • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
  • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
  • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
  • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.
  • Perhaps you forgot a new as in: String s = String(); // should be 'new String()'
  • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
  • Perhaps you are shadowing a static or instance variable.
  • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
  • Perhaps you are using (compiling against) the wrong version of an API.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnoord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon before the {. The Java language defines that to be an empty statement. So that code actually means this:

for (int i = 0; i < 100; i++); 

{
    System.out.println("i is " + i);
}

The { ... } block is NOT the body of the for loop, so the declaration of i is not in scope in the the block.

Here is another example of "Cannot find symbol" error that is caused by a typo.

int tmp = ...
int res = tmp(a + b);

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

for
for (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!

The point is that you need to understand what your code is trying to do in order to find the right fix.

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

You are looking at the wrong source code: It often happens that a new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like ...

IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

String s = ...
String s1 = s.substring(1);

It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

Lesson: Don't define your own classes with the same names as common library classes!

Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.

I had another situation where this compilation error occured while eclipse didn't see the problem: Two classes with dependencies defined in the respectively other class. In my case I had an enum, implementing an interface, defined in a class where I foolishly already used the enum.

Somewhat similarly to the comment above, when I compile and run my program from Eclipse it works no problem. Compiling it from the console raises a bunch of these "Cannot find symbol" errors often related to last element in an import. I have no idea what is causing this as there is nothing wrong in the code really.

@AndresStadelmann - Without seeing the code, I can't comment. If you want help from someone ask a Question.

@StephenC Hello! So here's the thing. The program that I wrote is a huge 13 week work in progress that I've only ever launched and compiled in eclipse. I'm working on implementing server functionalities and for that I would rather launch the program from a console with the required variables. The only feedback I've been getting from this is are these errors, so I casually came looking for answers online. Once I get really desperate I'll probably ask a more detailed question, but thanks for your concern. (Sorry for my ramble)

Also, for identifiers that are in a different class.

java - What does a "Cannot find symbol" compilation error mean? - Stac...

java compiler-errors cannot-find-symbol
Rectangle 27 235

1. What does a "Cannot find symbol" error mean?

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

Your Java source code consists of the following things:

true
false
class
while
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
Reader
toString
processEquibalancedElephants
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
  • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
  • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
  • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
  • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
  • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.
  • Perhaps you forgot a new as in: String s = String(); // should be 'new String()'
  • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
  • Perhaps you are shadowing a static or instance variable.
  • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
  • Perhaps you are using (compiling against) the wrong version of an API.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnoord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon before the {. The Java language defines that to be an empty statement. So that code actually means this:

for (int i = 0; i < 100; i++); 

{
    System.out.println("i is " + i);
}

The { ... } block is NOT the body of the for loop, so the declaration of i is not in scope in the the block.

Here is another example of "Cannot find symbol" error that is caused by a typo.

int tmp = ...
int res = tmp(a + b);

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

for
for (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!

The point is that you need to understand what your code is trying to do in order to find the right fix.

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

You are looking at the wrong source code: It often happens that a new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like ...

IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

String s = ...
String s1 = s.substring(1);

It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

Lesson: Don't define your own classes with the same names as common library classes!

Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.

I had another situation where this compilation error occured while eclipse didn't see the problem: Two classes with dependencies defined in the respectively other class. In my case I had an enum, implementing an interface, defined in a class where I foolishly already used the enum.

Somewhat similarly to the comment above, when I compile and run my program from Eclipse it works no problem. Compiling it from the console raises a bunch of these "Cannot find symbol" errors often related to last element in an import. I have no idea what is causing this as there is nothing wrong in the code really.

@AndresStadelmann - Without seeing the code, I can't comment. If you want help from someone ask a Question.

@StephenC Hello! So here's the thing. The program that I wrote is a huge 13 week work in progress that I've only ever launched and compiled in eclipse. I'm working on implementing server functionalities and for that I would rather launch the program from a console with the required variables. The only feedback I've been getting from this is are these errors, so I casually came looking for answers online. Once I get really desperate I'll probably ask a more detailed question, but thanks for your concern. (Sorry for my ramble)

Also, for identifiers that are in a different class.

java - What does a "Cannot find symbol" compilation error mean? - Stac...

java compiler-errors cannot-find-symbol
Rectangle 27 235

1. What does a "Cannot find symbol" error mean?

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

Your Java source code consists of the following things:

true
false
class
while
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
Reader
toString
processEquibalancedElephants
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
  • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
  • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
  • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
  • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
  • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.
  • Perhaps you forgot a new as in: String s = String(); // should be 'new String()'
  • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
  • Perhaps you are shadowing a static or instance variable.
  • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
  • Perhaps you are using (compiling against) the wrong version of an API.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnoord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon before the {. The Java language defines that to be an empty statement. So that code actually means this:

for (int i = 0; i < 100; i++); 

{
    System.out.println("i is " + i);
}

The { ... } block is NOT the body of the for loop, so the declaration of i is not in scope in the the block.

Here is another example of "Cannot find symbol" error that is caused by a typo.

int tmp = ...
int res = tmp(a + b);

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

for
for (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!

The point is that you need to understand what your code is trying to do in order to find the right fix.

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

You are looking at the wrong source code: It often happens that a new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like ...

IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

String s = ...
String s1 = s.substring(1);

It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

Lesson: Don't define your own classes with the same names as common library classes!

Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.

I had another situation where this compilation error occured while eclipse didn't see the problem: Two classes with dependencies defined in the respectively other class. In my case I had an enum, implementing an interface, defined in a class where I foolishly already used the enum.

Somewhat similarly to the comment above, when I compile and run my program from Eclipse it works no problem. Compiling it from the console raises a bunch of these "Cannot find symbol" errors often related to last element in an import. I have no idea what is causing this as there is nothing wrong in the code really.

@AndresStadelmann - Without seeing the code, I can't comment. If you want help from someone ask a Question.

@StephenC Hello! So here's the thing. The program that I wrote is a huge 13 week work in progress that I've only ever launched and compiled in eclipse. I'm working on implementing server functionalities and for that I would rather launch the program from a console with the required variables. The only feedback I've been getting from this is are these errors, so I casually came looking for answers online. Once I get really desperate I'll probably ask a more detailed question, but thanks for your concern. (Sorry for my ramble)

Also, for identifiers that are in a different class.

java - What does a "Cannot find symbol" compilation error mean? - Stac...

java compiler-errors cannot-find-symbol
Rectangle 27 227

1. What does a "Cannot find symbol" error mean?

Firstly, it is a compilation error1. It means that either there is a problem in your Java source code, or there is a problem in the way that you are compiling it.

Your Java source code consists of the following things:

true
false
class
while
  • Literals: like 42 and 'X' and "Hi mum!".
  • Operators and other non-alphanumeric tokens: like +, =, {, and so on.
Reader
toString
processEquibalancedElephants
  • Comments and whitespace.

A "Cannot find symbol" error is about the identifiers. When your code is compiled, the compiler needs to work out what each and every identifier in your code means.

A "Cannot find symbol" error means that the compiler cannot do this. Your code appears to be referring to something that the compiler doesn't understand.

As a first order, there is only one cause. The compiler looked in all of the places where the identifier should be defined, and it couldn't find the definition. This could be caused by a number of things. The common ones are as follows:

  • Perhaps you spelled the name incorrectly; i.e. StringBiulder instead of StringBuilder. Java cannot and will not attempt to compensate for bad spelling or typing errors.
  • Perhaps you got the case wrong; i.e. stringBuilder instead of StringBuilder. All Java identifiers are case sensitive.
  • Perhaps you used underscores inappropriately; i.e. mystring and my_string are different. (If you stick to the Java style rules, you will be largely protected from this mistake ...)
  • Perhaps the variable declaration is out of scope at the point you tried to use it. (See example below)
  • Perhaps you are trying to refer to an inherited method or field that wasn't declared in the parent / ancestor classes or interfaces.
  • Perhaps you are trying to use a method as a field, or vice versa; e.g. "someString".length or someArray.length().
  • Perhaps you used "star" imports, but the class isn't defined in any of the packages that you imported.
  • Perhaps you forgot a new as in: String s = String(); // should be 'new String()'
  • Perhaps you have declared a nested class or a generic parameter that shadows the type you were meaning to use.
  • Perhaps you are shadowing a static or instance variable.
  • Perhaps you imported the wrong type; e.g. due to IDE completion or auto-correction.
  • Perhaps you are using (compiling against) the wrong version of an API.

The problem is often a combination of the above. For example, maybe you "star" imported java.io.* and then tried to use the Files class ... which is in java.nio not java.io. Or maybe you meant to write File ... which is a class in java.io.

Here is an example of how incorrect variable scoping can lead to a "Cannot find symbol" error:

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnoord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

This will give a "Cannot find symbol" error for i in the if statement. Though we previously declared i, that declaration is only in scope for the for statement and its body. The reference to i in the if statement cannot see that declaration of i. It is out of scope.

(An appropriate correction here might be to move the if statement inside the loop, or to declare i before the start of the loop.)

Here is an example that causes puzzlement where a typo leads to a seemingly inexplicable "Cannot find symbol" error:

This will give you a compilation error in the println call saying that i cannot be found. But (I hear you say) I did declare it!

The problem is the sneaky semicolon before the {. The Java language defines that to be an empty statement. So that code actually means this:

for (int i = 0; i < 100; i++); 

{
    System.out.println("i is " + i);
}

The { ... } block is NOT the body of the for loop, so the declaration of i is not in scope in the the block.

Here is another example of "Cannot find symbol" error that is caused by a typo.

int tmp = ...
int res = tmp(a + b);

Despite the previous declaration, the tmp in the tmp(...) expression is erroneous. The compiler will look for a method called tmp, and won't find one. The previously declared tmp is in the namespace for variables, not the namespace for methods.

In the example I came across, the programmer had actually left out an operator. What he meant to write was this:

int res = tmp * (a + b);

There is another reason why the compiler might not find a symbol if you are compiling from the command line. You might simply have forgotten to compile or recompile some other class. For example, if you have classes Foo and Bar where Foo uses Bar. If you have never compiled Bar and you run javac Foo.java, you are liable to find that the compiler can't find the symbol Bar. The simple answer is to Foo and Bar together; e.g. javac Foo.java Bar.java or javac *.java. Or better still use a Java build tool; e.g. Ant, Maven, Gradle and so on.

Generally speaking, you start out by figuring out what caused the compilation error.

  • Look at the line in the file indicated by the compilation error message.
  • Identify which symbol that the error message is talking about.
  • Figure out why the compiler is saying that it cannot find the symbol; see above!

Then you think about what your code is supposed to be saying. Then finally you work out what correction you need to make to your source code to do what you want.

Note that not every "correction" is correct. Consider this:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Suppose that the compiler says "Cannot find symbol" for j. There are many ways I could "fix" that:

for
for (int j = 1; j < 10; j++)
  • I could add a declaration for j before the inner for loop, or the outer for loop - possibly correct.
  • I could change j to i in the inner for loop - probably wrong!

The point is that you need to understand what your code is trying to do in order to find the right fix.

Here are a couple of cases where the "Cannot find symbol" is seemingly inexplicable ... until you look closer.

You are looking at the wrong source code: It often happens that a new Java programmers don't understand how the Java tool chain works, or haven't implemented a repeatable "build process"; e.g. using an IDE, Ant, Maven, Gradle and so on. In such a situation, the programmer can end up chasing his tail looking for an illusory error that is actually caused by not recompiling the code properly, and the like ...

IDE issues: People have reported cases where their IDE gets confused and the compiler in the IDE cannot find a class that exists ... or the reverse situation.

Redefining system classes: I've seen cases where the compiler complains that substring is an unknown symbol in something like the following

String s = ...
String s1 = s.substring(1);

It turned out that the programmer had created their own version of String and that his version of the class didn't define a substring methods.

Lesson: Don't define your own classes with the same names as common library classes!

Homoglyphs: If you use UTF-8 encoding for your source files, it is possible to have identifiers that look the same, but are in fact different because they contain homoglyphs. See this page for more information.

You can avoid this by restricting yourself to ASCII or Latin-1 as the source file encoding, and using Java \uxxxx escapes for other characters.

I had another situation where this compilation error occured while eclipse didn't see the problem: Two classes with dependencies defined in the respectively other class. In my case I had an enum, implementing an interface, defined in a class where I foolishly already used the enum.

Somewhat similarly to the comment above, when I compile and run my program from Eclipse it works no problem. Compiling it from the console raises a bunch of these "Cannot find symbol" errors often related to last element in an import. I have no idea what is causing this as there is nothing wrong in the code really.

@AndresStadelmann - Without seeing the code, I can't comment. If you want help from someone ask a Question.

@StephenC Hello! So here's the thing. The program that I wrote is a huge 13 week work in progress that I've only ever launched and compiled in eclipse. I'm working on implementing server functionalities and for that I would rather launch the program from a console with the required variables. The only feedback I've been getting from this is are these errors, so I casually came looking for answers online. Once I get really desperate I'll probably ask a more detailed question, but thanks for your concern. (Sorry for my ramble)

Also, for identifiers that are in a different class.

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

java - What does a "Cannot find symbol" compilation error mean? - Stac...

java compiler-errors cannot-find-symbol
Rectangle 27 2

You misnamed your class it's called Hello while you seem to intend to call it Name. Also, note that constructors do not have return types in Java, not even void:

public class Name // Note the renaming
    {

    private String first;
    private String middle;
    private String last;


    public Name(String f, String m, String l) // Note the removal of void
    {
        first=f;
        middle=m;
        last=l;
    }

    public Name(String f, String l) // Note the removal of void
    {
        first=f;
        middle=" ";
        last=l;
    }

    public Name(String l) // Note the removal of void
    {
        first=" ";
        middle=" ";
        last=l;
    }

    // rest of the class

Also, don't forget to rename the file to Name.java instead of Hello.java.

"cannot find symbol" error in java class - Stack Overflow

java syntax-error cannot-find-symbol
Rectangle 27 1

NoClassDefFoundError means Java couldn't find the Class it was looking for. That normally means:

  • You defined wrongly the classpath.
  • Java is finding and using the wrong version of the jar (probably because of Maven dependency hell).

Solution for 1 is to check the classpath: make sure you are including the jar that defines org.apache.spark.sql.SchemaRDD.

Solution for 2 is to check if you have a Maven dependency that depends (transitively) on an older version of the resource that defines that class.

java.lang.NoClassDefFoundError: org/apache/spark/sql/SchemaRDD - Stack...

java apache-spark apache-spark-sql
Rectangle 27 386

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.

A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}

This answer does provide a valid solution but it is inaccurate to say there is no way to find the generic type at runtime. It turns out type erasure is far more complex than a blanket erasure. My answer shows you how to get the classes generic type.

@BenThurley Neat trick, but as far as I can see it only works if there is a generic supertype for it to use. In my example, you can't retrieve the type of T in Foo<T>.

Fair point about a generic supertype. I can't think of an occasion where I've used generics without one though, except in exam questions. I've added the extra detail to my answer to make it clearer. Thanks.

@ses I've yet to see a language that is. They're all a compromise in one way or another. Anyone who tells you otherwise has yet to learn. ;)

java - How to get a class instance of generics type T - Stack Overflow

java generics
Rectangle 27 379

The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. I suggest reading the chapter about type erasure in the Java Tutorial for more details.

A popular solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.

class Foo<T> {
    final Class<T> typeParameterClass;

    public Foo(Class<T> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    public void bar() {
        // you can access the typeParameterClass here and do whatever you like
    }
}

This answer does provide a valid solution but it is inaccurate to say there is no way to find the generic type at runtime. It turns out type erasure is far more complex than a blanket erasure. My answer shows you how to get the classes generic type.

@BenThurley Neat trick, but as far as I can see it only works if there is a generic supertype for it to use. In my example, you can't retrieve the type of T in Foo<T>.

Fair point about a generic supertype. I can't think of an occasion where I've used generics without one though, except in exam questions. I've added the extra detail to my answer to make it clearer. Thanks.

@ses I've yet to see a language that is. They're all a compromise in one way or another. Anyone who tells you otherwise has yet to learn. ;)

java - How to get a class instance of generics type T - Stack Overflow

java generics
Rectangle 27 8

Bluetooth devices with class 0x00 are ignored

So, here's all I found after reading blogs, threads, documentations, SO answers etc. regarding Android's bluetooth discovery. Thought this might be useful to post my findings here.

I could not find any way to detect a bluetooth device nearby which is turned on but not discoverable.

My primary target is to detect all nearby bluetooth devices. To do so, we have a BluetoothAdapter class in Android which has a startDiscovery function to scan for bluetooth devices nearby. Hence, this doesn't serves my purpose, as the bluetooth devices need to be discoverable to be detected by a bluetooth scan by Android. What I want is to detect all Bluetooth devices nearby without forcing them to be discoverable. I started searching for a solution to achieve this goal.

I started with studying Bluetooth protocols and found the underlying protocols used for bluetooth detection, connection and pairing. For Android, I found no API to discover/detect BT devices which are turned on but not in discoverable mode.

Digging into this detection problem without forcing the bluetooth devices to discoverable mode lead us to a point where we found Bluetooth device which advertises itself as class 000 is ignored automatically while running scan for nearby BT devices. This problem is stated in several places. Here I have listed some.

I tried to find a work-around of this problem and yes, I found one, though the documentation and reviews along with this work-around says, it doesn't work for all kind of Android devices. Anyway, the alternate scan is the same as the default BT scan, but it does some additional works. It reads the Android log after a successful BT scan and check if there's any BT device is skipped through out the operation. This is a simple hack described here . There's a google group discussing about the same work-around here.

The work-around above doesn't solve my problem either. Bluetooth headsets need to be discoverable for being detected by a BT scan. They are not skipped while Android is scanning nearby BT devices. They are simply not found.

It is possible to know whether a bluetooth device is around, even if he is in an undiscoverable mode, by knowing his full MAC address in the first place

The technique is to try a PAGE request, sending all the 6 bytes that are composing the seeked Bluetooth host MAC identifier. A PAGE request allows one to connect with a Bluetooth slave when knowing his BT ADDR. Devices that are in undiscoverable mode does not respond to inquiry scan (device discovery intent), but they do respond to page scan which is used by a device wanting to connect to an another previously known device.

I found hope and started searching for, how can we initiate a page scan in Android but failed this time too. Couldn't find any kind of APIs to initiate page scan. From Android documentation of BluetoothAdapter class, I came to know that, when a BT scan starts,

This usually involves an inquiry scan of about 12 seconds, followed by a page scan of each new device to retrieve its Bluetooth name.

There is an indication of page scan in Android documentation, but, surprisingly, there is no other documentation regarding page scan anywhere. I put a Stackoverflow question for inquiry.

No, I did not find any way to do so. I read about how Android's bluetooth pairing works. Here is a nice flow diagram along with detailed reading manual. We were trying to use Android's hidden APIs and could use some hidden APIs using Reflection. Then we started to look for hidden APIs which we might use to serve my purpose. But, unfortunately, we failed to find any hidden APIs to add a BT device in Android's already paired list programatically.

Here are some helpful links to check for bluetooth pairing, hidden APIs and how to invoke them via reflection for future reference.

So I could pair a BT device when it was in discoverable mode and was not in the paired list in Android. In my case, I used a bluetooth headset. It was turned on and put in discoverable mode. The BT Address (MAC address) of the headset was known. So I called the function createBond from my code using reflection and it worked perfectly. The device was added in the "already-paired" list of Android successfully. While roaming around for solutions to serve my purpose I found something interesting...

I found that, android preserves a previously paired device in its memory even if I remove it from the already-paired list. Let us share a case study along with the findings here for a better understanding. In my case the headset was paired previously.

  • Unpaired/forget the headset from Android
  • Then turned the headset off.
  • Of course, the headset was not found
  • But we went through the Android logs and found that, Android remembers the change of bonding state (paring state) of that headset.
  • It scanned for the previously bonded headphone and reported remote device is down

Here is the log that printed along with the MAC address of the headset we paired before and then unpaired.

Then again, I ran the same test, but this time we turned the bluetooth headset on (not discoverable). The headset was not found in this case too, but the interesting thing is, this time a different log was printed.

PREV_BOND_STATE = 11 // BOND_BONDING    (BluetoothDevice.java)
BOND_STATE = 10      // BOND_NONE
REASON = 2           // UNBOND_REASON_AUTH_CANCELLED

The REASON is changed and hence I can understand Android tried to connect with the bluetooth headset. The headset was not in discoverable mode, yet Android could find it and tried to connect with it as it was in paired list before.

This log was printed while a bluetooth scan was running with adding ACTION_BOND_STATE_CHANGED action with intent.addAction.

Yes, but in that case Android needs to advertise itself as a BLE too. This is what new in Android and not all devices support this functionality till now. Here is a list of devices which support Bluetooth LE advertisement capability. But, as Bluetooth LE advertisement has a very low power consumption along with a high performance, I think this will be the next big thing in Android.

android - Detect all Bluetooth devices (headsets, phones etc) nearby, ...

android bluetooth bluetooth-lowenergy android-bluetooth