¿Qué significa "No se pudo encontrar o cargar la clase principal"?

1370

Un problema común que experimentan los nuevos desarrolladores de Java es que sus programas no se ejecutan con el mensaje de error: Could not find or load main class ...

¿Qué significa esto, qué lo causa y cómo debe solucionarlo?

Stephen C
fuente
37
Tenga en cuenta que esta es una pregunta de "respuesta propia" que pretende ser una referencia genérica de preguntas y respuestas para los nuevos usuarios de Java. No pude encontrar un Q&A existente que cubra esto adecuadamente (IMO).
Stephen C

Respuestas:

1230

La java <class-name>sintaxis del comando

En primer lugar, debe comprender la forma correcta de iniciar un programa utilizando el comando java(o javaw).

La sintaxis normal 1 es esta:

    java [ <options> ] <class-name> [<arg> ...]

donde <option>es una opción de línea de comando (que comienza con un carácter "-"), <class-name>es un nombre de clase Java totalmente calificado y <arg>es un argumento arbitrario de línea de comando que se pasa a su aplicación.


1 - Hay algunas otras sintaxis que se describen cerca del final de esta respuesta.

El nombre completo (FQN) para la clase se escribe convencionalmente como lo haría en el código fuente de Java; p.ej

    packagename.packagename2.packagename3.ClassName

Sin embargo, algunas versiones del javacomando le permiten usar barras en lugar de puntos; p.ej

    packagename/packagename2/packagename3/ClassName

que (confusamente) parece un nombre de ruta de archivo, pero no lo es. Tenga en cuenta que el término nombre totalmente calificado es terminología estándar de Java ... no es algo que acabo de inventar para confundirlo :-)

Aquí hay un ejemplo de cómo javadebería verse un comando:

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

Lo anterior va a causar el java comando haga lo siguiente:

  1. Busque la versión compilada de com.acme.example.ListUsers clase.
  2. Carga la clase.
  3. Verifique que la clase tenga un mainmétodo con firma , tipo de retorno y modificadores dados por public static void main(String[]). (Tenga en cuenta que el nombre del argumento del método NO es parte de la firma).
  4. Llame a ese método pasándole los argumentos de la línea de comando ("fred", "joe", "bert") como a String[].

Razones por las cuales Java no puede encontrar la clase

Cuando recibe el mensaje "No se pudo encontrar o cargar la clase principal ...", eso significa que el primer paso ha fallado. El javacomando no pudo encontrar la clase. Y de hecho, el "..." en el mensaje será el nombre de clase completo que javaestá buscando.

Entonces, ¿por qué podría ser incapaz de encontrar la clase?

Razón # 1 - cometiste un error con el argumento del nombre de clase

La primera causa probable es que puede haber proporcionado el nombre de clase incorrecto. (O ... el nombre de clase correcto, pero en forma incorrecta.) Considerando el ejemplo anterior, aquí hay una variedad de formas incorrectas de especificar el nombre de clase:

  • Ejemplo # 1 - un nombre de clase simple:

    java ListUser

    Cuando la clase se declara en un paquete como com.acme.example, entonces debe usar el nombre de clase completo, incluido el nombre del paquete en el javacomando; p.ej

    java com.acme.example.ListUser
  • Ejemplo # 2 - un nombre de archivo o ruta en lugar de un nombre de clase:

    java ListUser.class
    java com/acme/example/ListUser.class
  • Ejemplo # 3 - un nombre de clase con la carcasa incorrecta:

    java com.acme.example.listuser
  • Ejemplo # 4 - un error tipográfico

    java com.acme.example.mistuser
  • Ejemplo # 5 - un nombre de archivo fuente (excepto para Java 11 o posterior; ver más abajo)

    java ListUser.java
  • Ejemplo # 6 - olvidaste el nombre de la clase por completo

    java lots of arguments

Razón n. ° 2: la ruta de clase de la aplicación está especificada incorrectamente

La segunda causa probable es que el nombre de la clase es correcto, pero que el javacomando no puede encontrar la clase. Para comprender esto, debe comprender el concepto de "classpath". Esto se explica bien en la documentación de Oracle:

Entonces ... si ha especificado el nombre de la clase correctamente, lo siguiente que debe verificar es que haya especificado la ruta de clase correctamente:

  1. Lea los tres documentos vinculados anteriormente. (Sí ... ¡LÉELOS! Es importante que un programador de Java entienda al menos los conceptos básicos de cómo funcionan los mecanismos de classpath de Java).
  2. Mire la línea de comando y / o la variable de entorno CLASSPATH que está vigente cuando ejecuta el comando java comando. Compruebe que los nombres de directorio y los nombres de archivo JAR son correctos.
  3. Si hay nombres de ruta relativos en el classpath, verifique que se resuelvan correctamente ... desde el directorio actual que está vigente cuando ejecuta el javacomando.
  4. Verifique que la clase (mencionada en el mensaje de error) pueda ubicarse en la ruta de clase efectiva .
  5. Tenga en cuenta que la sintaxis de classpath es diferente para Windows frente a Linux y Mac OS. (El separador de classpath está ;en Windows y :en los demás. Si usa el separador incorrecto para su plataforma, no recibirá un mensaje de error explícito. En su lugar, obtendrá un archivo o directorio inexistente en la ruta que se ignorará en silencio .)

Motivo # 2a: el directorio incorrecto está en el classpath

Cuando coloca un directorio en el classpath, teóricamente corresponde a la raíz del espacio de nombre calificado. Las clases se encuentran en la estructura de directorios debajo de esa raíz, asignando el nombre completo a un nombre de ruta . Entonces, por ejemplo, si "/ usr / local / acme / classes" está en la ruta de clase, cuando la JVM busca una clase llamada com.acme.example.Foon, buscará un archivo ".class" con este nombre de ruta:

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

Si hubiera puesto "/ usr / local / acme / classes / com / acme / example" en el classpath, entonces la JVM no podría encontrar la clase.

Motivo # 2b: la ruta del subdirectorio no coincide con el FQN

Si sus clases son FQN com.acme.example.Foon, entonces la JVM buscará "Foon.class" en el directorio "com / acme / example":

  • Si la estructura de su directorio no coincide con el nombre del paquete según el patrón anterior, la JVM no encontrará su clase.

  • Si intenta cambiar el nombre de una clase moviéndola, eso también fallará ... pero la excepción stacktrace será diferente. Es probable que diga algo como esto:

    Caused by: java.lang.NoClassDefFoundError: <path> (wrong name: <name>)

    porque el FQN en el archivo de clase no coincide con lo que el cargador de clases espera encontrar.

Para dar un ejemplo concreto, suponiendo que:

  • quieres correr com.acme.example.Foonclase,
  • la ruta completa del archivo es /usr/local/acme/classes/com/acme/example/Foon.class,
  • su directorio de trabajo actual es /usr/local/acme/classes/com/acme/example/,

entonces:

# 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

Notas:

  • La -classpathopción se puede acortar -cpen la mayoría de las versiones de Java. Verifique las entradas manuales respectivas para java, javacetc.
  • Piensa cuidadosamente al elegir entre nombres de ruta absolutos y relativos en classpaths. Recuerde que un nombre de ruta relativo puede "romperse" si cambia el directorio actual.

Razón # 2c - faltan dependencias de la ruta de clase

El classpath debe incluir todas las otras clases (no del sistema) de las que depende su aplicación. (Las clases del sistema se ubican automáticamente, y rara vez necesita preocuparse por esto.) Para que la clase principal se cargue correctamente, la JVM necesita encontrar:

(Nota: las especificaciones JLS y JVM permiten cierto alcance para que una JVM cargue clases "perezosamente", y esto puede afectar cuando se produce una excepción de cargador de clases).

Razón n. ° 3: la clase se ha declarado en el paquete incorrecto

Ocasionalmente sucede que alguien coloca un archivo de código fuente en la carpeta incorrecta en su árbol de código fuente, o deja de lado la packagedeclaración. Si hace esto en un IDE, el compilador del IDE le informará sobre esto inmediatamente. Del mismo modo, si utiliza una herramienta de compilación Java decente, la herramienta se ejecutará javacde manera que detecte el problema. Sin embargo, si crea su código Java a mano, puede hacerlo de tal manera que el compilador no note el problema y el archivo ".class" resultante no esté en el lugar que espera que esté.

¿Aún no puedes encontrar el problema?

Hay muchas cosas para verificar, y es fácil perderse algo. Intente agregar la -Xdiagopción a la javalínea de comando (como lo primero después java). Producirá varias cosas sobre la carga de clases, y esto puede ofrecerle pistas sobre cuál es el verdadero problema.

Además, tenga en cuenta los posibles problemas causados ​​por copiar y pegar caracteres invisibles o no ASCII de sitios web, documentos, etc. Y considere "homoglifos", donde dos letras o símbolos se ven iguales ... pero no lo son.

Finalmente, aparentemente puede encontrarse con este problema si intenta iniciar desde un archivo JAR con firmas incorrectas (META-INF/*.SF).


Sintaxis alternativas para java

Existen tres sintaxis alternativas para el lanzamiento de programas Java utilizando java command.

1) La sintaxis utilizada para iniciar un archivo JAR "ejecutable" es la siguiente:

  java [ <options> ] -jar <jar-file-name> [<arg> ...]

p.ej

  java -Xmx100m -jar /usr/local/acme-example/listuser.jar fred

El nombre de la clase de punto de entrada (es decir com.acme.example.ListUser) y el classpath se especifican en el MANIFEST del archivo JAR.

2) La sintaxis para iniciar una aplicación desde un módulo (Java 9 y posterior) es la siguiente:

  java [ <options> ] --module <module>[/<mainclass>] [<arg> ...]

El nombre de la clase de punto de entrada está definido por el <module>mismo o está dado por el opcional <mainclass>.

3) A partir de Java 11, puede compilar y ejecutar un único archivo de código fuente y ejecutarlo con la siguiente sintaxis:

  java [ <options> ] <sourcefile> [<arg> ...]

donde es (típicamente) un archivo con el sufijo ".java".

Para obtener más detalles, consulte la documentación oficial del javacomando para la versión de Java que está utilizando.


IDEs

Un IDE Java típico tiene soporte para ejecutar aplicaciones Java en la JVM IDE o en una JVM secundaria. En general, son inmunes a esta excepción particular, porque el IDE utiliza sus propios mecanismos para construir el classpath en tiempo de ejecución, identificar la clase principal y crear la javalínea de comando.

Sin embargo, todavía es posible que ocurra esta excepción, si hace cosas detrás del IDE. Por ejemplo, si previamente configuró un Lanzador de aplicaciones para su aplicación Java en Eclipse, y luego movió el archivo JAR que contiene la clase "principal" a un lugar diferente en el sistema de archivos sin decirle a Eclipse , Eclipse lanzaría involuntariamente la JVM con una ruta de clase incorrecta.

En resumen, si tiene este problema en un IDE, verifique cosas como el estado de IDE obsoleto, referencias de proyecto rotas o configuraciones de iniciador rotas.

También es posible que un IDE simplemente se confunda. Los IDE son piezas de software enormemente complicadas que comprenden muchas partes interactivas. Muchas de estas partes adoptan varias estrategias de almacenamiento en caché para que el IDE en su conjunto responda. A veces, estos pueden salir mal, y un síntoma posible son los problemas al iniciar aplicaciones. Si sospecha que esto podría estar sucediendo, vale la pena intentar otras cosas como reiniciar su IDE, reconstruir el proyecto, etc.


Otras referencias

Stephen C
fuente
43
Tuve este problema cuando intentaba ejecutar una clase con una biblioteca de terceros. Invoqué java como esto: java -cp ../third-party-library.jar com.my.package.MyClass; esto no funciona, en su lugar, es necesario agregar la carpeta local a la ruta de la clase también (separada por :, así:, java -cp ../third-party-library.jar:. com.my.package.MyClassentonces debería funcionar
lanoxx
23
Después de años de programación en Java, todavía logré terminar en esta página. Para mí, el problema era que la sintaxis de classpath depende del sistema operativo . Soy un poco nuevo en la programación en Windows y no tenía idea.
keyser
55
Notas adicionales, punto 2 ¡sálvame! Es triste ver que javano dice que no encuentra una clase importada, sino la clase principal que está intentando ejecutar. Esto es engañoso, aunque estoy seguro de que hay una razón para eso. Tuve el caso donde javasabía exactamente dónde está mi clase, sin embargo, no pudo encontrar una de las clases importadas. En lugar de decir eso, se quejó de no encontrar a mi clase principal. Realmente molesto.
MSX
Tuve este problema dos veces en Eclipse. Primera vez que la firma de main () estaba equivocada. La segunda vez que renombré un archivo .jar, y aunque agregué el nuevo a la ruta de compilación, Eclipse no encontró el anterior, por lo que el proyecto no se compiló con este error. Tuve que eliminar el archivo .jar de Proyecto> Propiedades> Ruta de compilación de Java> Bibliotecas.
GregT
Lo he encontrado por tercera vez. Ejecuté el programa desde un archivo por lotes de Windows 10 y puse el nombre .jar en una variable (llamada con "-cp% jarname%; lib *"). Por error, puse un espacio extra al final del nombre del jar, y causó el error. Hat trick :)
GregT
239

Si su nombre de código fuente es HelloWorld.java, su código compilado lo será HelloWorld.class.

Obtendrá ese error si lo llama usando:

java HelloWorld.class

En cambio, use esto:

java HelloWorld
panoet
fuente
3
El problema es que esta solución solo funciona para las clases Java declaradas en el paquete predeterminado sin dependencias de archivos JAR. (Y aun así, no todo el tiempo). La mayoría de los programas Java no son tan simples.
Stephen C
1
como dijo Stephen, esto solo funciona con el "paquete predeterminado", lo que significa que no hay declaración de paquete en la parte superior del archivo. Para una prueba rápida de algún código, lo hice: javac TestCode.javaseguido dejava TestCode
Someone Somewhere
Esto no funcionó para mí. Todavía dice: "No se pudo encontrar o cargar la clase principal HelloWorld"
Jim
java -jar HelloWorld.jar también es una opción
BMaximus
12
Tenía que hacerlojava -classpath . HelloWorld
Chris Prince
136

Si sus clases están en paquetes , debe cdacceder al directorio raíz de su proyecto y ejecutarlo utilizando el nombre completo de la clase (packageName.MainClassName).

Ejemplo:

Mis clases están aquí:

D:\project\com\cse\

El nombre completo de mi clase principal es:

com.cse.Main

Así que cdvuelvo al directorio raíz del proyecto:

D:\project

Luego emita el javacomando:

java com.cse.Main

Esta respuesta es para rescatar a los programadores novatos de Java de la frustración causada por un error común, le recomiendo que lea la respuesta aceptada para obtener un conocimiento más profundo sobre el classpath de Java.

tharinduwijewardane
fuente
2
Esta respuesta hace un montón de suposiciones. Y hay otras formas de lograr esto. En lugar de seguir ciegamente los consejos anteriores, recomendaría que la gente se tome el tiempo de leer los enlaces en mi Respuesta que explican cómo funciona el classpath de Java. Es mejor ENTENDER lo que estás haciendo ...
Stephen C
2
Esta respuesta hace las suposiciones exactas que necesitaba :) Estaba ubicado en el directorio del archivo .class y java.exe no funcionaba. Una vez que hice el CD arriba y ejecuté el nombre del paquete incluido en la línea de comando, funcionó.
Nick Constantine
61

Si define la clase principal y el método principal en apackage , debe ejecutarlo sobre el directorio jerárquico, utilizando el nombre completo de la clase ( packageName.MainClassName).

Suponga que hay un archivo de código fuente (Main.java):

package com.test;

public class Main {

    public static void main(String[] args) {
        System.out.println("salam 2nya\n");
    }
}

Para ejecutar este código, debe colocarlo Main.Classen el paquete como directorio ./com/test/Main.Java. Y en el directorio raíz use java com.test.Main.

M-Razavi
fuente
1
Consulte "Notas adicionales # 1" de mi respuesta. Para una mejor explicación de este problema.
Stephen C
14
@StephenC Sí, su respuesta es más completa (y, por supuesto, +1), pero esta respuesta en particular tenía la palabra "paquete", lo que me permitió encontrar lo que necesitaba rápidamente. Y funcionó. Entonces +1 Razavi. StephenC, el tuyo carece del ejemplo de paquete simple que necesitaba porque soy nuevo en Java.
kmort
55
Este fue exactamente mi problema. He estado vadeando toneladas de documentos de Java y este ejemplo concreto es lo que necesitaba
John
1
Sí, un ejemplo concreto es bueno, esto funcionó perfectamente. Estoy seguro de que la respuesta principal es muy exhaustiva, pero fue difícil ver el árbol del bosque. Nice one @Razavi
Pixel
1
¡Me gusta esta respuesta más corta y útil en lugar de una aceptada!
Spara
46

Cuando el mismo código funciona en una PC, pero muestra el error en otra, la mejor solución que he encontrado es compilar de la siguiente manera:

javac HelloWorld.java
java -cp . HelloWorld
Enamul Hassan
fuente
2
Esta no es una buena recomendación. Depende de que la variable de entorno CLASSPATH no esté configurada o tenga un valor que sea consistente con "." Sí, funciona en muchos casos, pero no lo hará en otros.
Stephen C
Bueno, ciertamente javac -classpath . HelloWorld.javahabría funcionado! Y esa es una mejor solución en su caso.
Stephen C
2
Si tiene 'package com.some.address' como primera línea, esto no funcionará. Tendrá que comentar 'dirección del paquete' ..
Joe
1
@ Joe - Ese truco (comentar el paquete) funcionará (en algunos casos) pero es una mala idea. Una mejor idea es aprender / comprender qué causó el problema e implementar la solución correcta.
Stephen C
36

Lo que me ayudó fue especificar el classpath en la línea de comando, por ejemplo:

  1. Crear una nueva carpeta, C:\temp

  2. Cree el archivo Temp.java en C:\temp, con la siguiente clase en él:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
  3. Abra una línea de comando en la carpeta C:\tempy escriba el siguiente comando para compilar la clase Temp:

    javac Temp.java
  4. Ejecute la clase Java compilada, agregando la -classpathopción para que JRE sepa dónde encontrar la clase:

    java -classpath C:\temp Temp Hello!
Celebra
fuente
3
En Ubuntu, también tuve que especificar la ruta. No entiendo por qué no puede usar el Directorio de trabajo actual de forma predeterminada. ¡Estoy convencido de que Java está patrocinado por los fabricantes de teclados!
desapareció el
1
@gone - La razón por la que "." no está en $ PATH por defecto es que es una trampa de seguridad. seas.upenn.edu/cets/answers/dot-path.html
Stephen C
Muchas gracias por esto ... aunque no estoy seguro de por qué Java no pudo encontrar el classpath incluso después de configurarlo en variables de entorno.
akash89
@ akash89: las razones más probables fueron: 1) javano estaba mirando $ CLASSPATH (porque usó -classpath o -jar) o 2) la configuración de classpath no se estableció en el entorno que no estaba en vigor en el contexto que javaera correr; por ejemplo, porque no "fuente" el archivo donde se agregaron los comandos setenv en el shell derecho.
Stephen C
Todavía recibí Error: ¡No pude encontrar o cargar la clase principal Temp, alguien podría ayudarme!
Estrella
27

Según el mensaje de error ("No se pudo encontrar o cargar la clase principal"), hay dos categorías de problemas:

  1. No se pudo encontrar la clase principal
  2. No se pudo cargar la clase principal (este caso no se analiza completamente en la respuesta aceptada)

No se pudo encontrar la clase principal cuando hay un error tipográfico o una sintaxis incorrecta en el nombre completo de la clase o no existe en el classpath proporcionado .

La clase principal no se pudo cargar cuando la clase no se puede iniciar , normalmente la clase principal extiende otra clase y esa clase no existe en el classpath proporcionado.

Por ejemplo:

public class YourMain extends org.apache.camel.spring.Main

Si camel-spring no está incluido, se informará este error.

Xiao Peng - ZenUML.com
fuente
"Básicamente" también hay muchas otras categorías. Y el problema de la superclase que falta es un subcase muy inusual. (Tan inusual que nunca lo he visto ... en las preguntas formuladas en este sitio.)
Stephen C
Hay DOS porque el error dice "No se pudo ENCONTRAR o CARGAR la clase principal". Si hay otras categorías, avísenme. Lo he visto, así que solo quiero compartirlo aquí, tal vez alguien más lo necesite.
Xiao Peng - ZenUML.com
1
Lo habría revisado a algo como "Debe incluir todas las clases que se requieren para iniciar la clase principal para evitar este error en particular". No estoy tratando de convencerte. Es solo una forma que me gustaría ver. Dejé la respuesta aquí solo para las personas a las que les gustaría leer las cosas de esta manera. No ampliemos más esta discusión :) Cambié mi declaración a "no discutido completamente en la respuesta aceptada" y espero que se sienta mejor.
Xiao Peng - ZenUML.com
55
Esta información es crucial y merece una mención explícita (esta es la única respuesta que menciona extends). Acabo de aprender de la manera difícil que cuando la clase principal no se carga porque extiende otra que no se pudo encontrar , Java no informa qué clase real no se encontró (a diferencia deNoClassDefFoundError ). Entonces sí, sucede, y es una situación desgarradora cuando no se sabe esto.
Hugues M.
1
En esta situación, ¿hay alguna forma de saber exactamente qué clase de dependencia no se puede cargar?
Carlos A. Ibarra
16

Tuve tal error en este caso:

java -cp lib.jar com.mypackage.Main

Funciona con ;Windows y :Unix:

java -cp lib.jar; com.mypackage.Main
Yamahar1sp
fuente
Si. Eso es muy probable porque su Mainno está en el archivo JAR. -cp lib.jar;significa lo mismo que -cp lib.jar;. el directorio actual está incluido en el classpath.
Stephen C
Finalmente solucioné el problema de Unix ... gracias (funciona con :)
Vicky
16

Prueba -Xdiag .

La respuesta de Steve C cubre muy bien los posibles casos, pero a veces determinar si no se pudo encontrar o cargar la clase podría no ser tan fácil. Uso java -Xdiag(desde JDK 7). Esto imprime un buen stacktrace que proporciona una pista de lo que significa el mensaje de Could not find or load main classmensaje.

Por ejemplo, puede señalar otras clases utilizadas por la clase principal que no se pudieron encontrar y evitar que se cargue la clase principal.

jan.supol
fuente
16

Usa este comando:

java -cp . [PACKAGE.]CLASSNAME

Ejemplo: si su nombre de clase es Hello.class creado a partir de Hello.java, utilice el siguiente comando:

java -cp . Hello

Si su archivo Hello.java está dentro del paquete com.demo, utilice el siguiente comando

java -cp . com.demo.Hello

Con JDK 8 muchas veces sucede que el archivo de clase está presente en la misma carpeta, pero el javacomando espera classpath y por esta razón agregamos -cp .para tomar la carpeta actual como referencia para classpath.

shaILU
fuente
Esto solo funciona en casos simples. Los casos más complicados requieren un classpath más complicado.
Stephen C
Y para >> realmente << casos simples, -cp .es innecesario, porque si no $CLASSPATHestá configurado, entonces .es el classpath predeterminado.
Stephen C
No, Stephen, muchas veces en el classpath predeterminado de Windows no funciona. Lo probé en tres máquinas diferentes, también puedes probarlo.
shaILU
Probablemente se deba a que ha configurado la variable de entorno% CLASSPATH% en alguna parte. Si haces eso, entonces no estás usando la ruta de clase predeterminada. (¿Qué genera la echo %CLASSPATH%salida?) Y no, no puedo comprobarlo porque no tengo una PC con Windows.
Stephen C
2
Esto funcionó para mí cuando intenté ejecutar un programa simple desde la línea de comandos
SnuKies
15

A veces, lo que podría estar causando el problema no tiene nada que ver con la clase principal, y tuve que averiguarlo por las malas. Era una biblioteca referenciada que moví, y me dio el:

No se pudo encontrar o cargar Linux de clase principal xxx

Acabo de eliminar esa referencia, la agregué nuevamente y funcionó bien nuevamente.

Eduardo Dennis
fuente
1
Parece que el problema era que tenía una ruta de clase incorrecta debido a una "referencia" rota en su proyecto en su IDE. Actualizaré mi respuesta para cubrir ese caso.
Stephen C
@StephenC y EduardoDennis, fue que aquí también faltaba un jar, ese jar contenía una interfaz de la que dependía la clase principal para instanciarse. Entonces, el mensaje de error es demasiado amplio. Debo decir "no se pudo encontrar" si no se encuentra el archivo de clase y "no se pudo cargar (dependencias faltantes)" si falta algo más pero no el archivo en sí mismo, por lo que el mensaje de error que es demasiado amplio es engañoso si solo se enfoca en la parte "encontrar" :(
Acuario de energía
@AquariusPower: debería haber habido un seguimiento adicional "causado por" para la excepción de "causa" que decía que faltaba la clase. Si desea sugerir a los desarrolladores de Java que cambien un mensaje de error que lleva más de 20 años diciendo ... siéntase libre. (Creo que el mensaje de error es correcto. El problema fue que >> usted << aclaró la cláusula incorrecta.)
Stephen C
Lo que quise decir con @StephenC es que seguramente tienen acceso a la información si el archivo de clase principal está disponible o no, entonces, ¿por qué no nos muestran un mejor mensaje de error diciendo que falta ese archivo? Por otro lado, también podrían decir "Se encontró el archivo pero no se pudo cargar" en ese momento, nos enfocaríamos rápidamente en las dependencias en lugar de perder medio día investigando y probando cosas para comprender. Solo que quise decir :). Pueden hacerlo de forma limitada durante más de 20 años, pero pueden mejorarlo y estamos aquí para garantizar que sucederá a través de nuestras críticas y quejas. : D
Acuario Power
Por favor, comprenda lo que >> I << quiso decir. Quejarse al respecto en algún comentario oscuro sobre preguntas y respuestas de 3 años no va a lograr nada. Las personas que podrían actuar de manera conciente sobre sus quejas no lo notarán. Si quieres hacer algo constructivo, envía un parche. (No califico sus posibilidades, pero serán mayores que si simplemente se queja).
Stephen C
10

En este caso tienes:

No se pudo encontrar o cargar la clase principal ? Classpath

Es porque está utilizando "-classpath", pero el guión no es el mismo guión utilizado javaen el símbolo del sistema. Tuve este problema al copiar y pegar desde el Bloc de notas a cmd.

Nathan Williams
fuente
2
¡Guauu! ¡Esa es una causa totalmente extraña! (Pero le sirve para usar el Bloc de notas en lugar de un editor de texto real :-))
Stephen C
10

Tuve el mismo problema y finalmente encontré mi error :) Utilicé este comando para compilar y funcionó correctamente:

javac -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode.java

Pero este comando no funcionó para mí (no pude encontrar ni cargar la clase principal qrcode):

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar" qrcode

Finalmente, simplemente agregué el carácter ':' al final de la ruta de clase y el problema se resolvió:

java -cp "/home/omidmohebbi/AAAATest/jars/core-1.7.jar:/home/omidmohebbi/AAAATest/jars/javase-1.7.jar:/home/omidmohebbi/AAAATest/jars/qrgen-1.2.jar:" qrcode
Omid Mohebbi
fuente
7

En mi caso, apareció un error porque había proporcionado el nombre del archivo de origen en lugar del nombre de la clase.

Necesitamos proporcionar el nombre de la clase que contiene el método principal al intérprete.

KawaiKx
fuente
Si. ¡Vea mi ejemplo # 2 de las formas incorrectas de especificar el nombre de la clase!
Stephen C
7

Esto podría ayudarlo si su caso es específicamente como el mío: como principiante, también me encontré con este problema cuando intenté ejecutar un programa Java.

Lo compilé así:

javac HelloWorld.java

Y traté de ejecutar también con la misma extensión:

java Helloworld.java

Cuando eliminé .javay reescribí el comando como java HelloWorld, el programa se ejecutó perfectamente. :)

Ramesh Pareek
fuente
2
Esto se debe a que está ejecutando la versión compilada de su .java. En realidad está ejecutando el archivo .class
Jason V
Para el registro, esto es lo mismo que la Razón # 1, Ejemplo # 5 en mi respuesta ...
Stephen C
6

Parece que todas las respuestas aquí están dirigidas a usuarios de Windows. Para Mac, el separador de classpath es :, no ;. Como error al configurar el classpath usando; no se , esto puede ser difícil de descubrir si viene de Windows a Mac.

Aquí está el comando correspondiente de Mac:

java -classpath ".:./lib/*" com.test.MyClass

En este ejemplo, dónde está el paquete com.testy libse debe incluir una carpeta en classpath.

cielo azul
fuente
2
En Linux al igual que en Mac.
Alex78191
¿Por qué /*es necesario?
Alex78191
Es una sintaxis comodín. (No es obligatorio. Puede enumerar explícitamente los JAR si lo desea).
Stephen C
6

ingrese la descripción de la imagen aquí

Ubicación del archivo de clase: C: \ test \ com \ company

Nombre del archivo: Main.class

Nombre de clase completo: completo com.company.Main

Comando de línea de comando:

java  -classpath "C:\test" com.company.Main

Tenga en cuenta que la ruta de clase NO incluye \ com \ company

desarrollador747
fuente
6

Pasé una cantidad de tiempo decente tratando de resolver este problema. Pensé que de alguna manera estaba configurando mi classpath incorrectamente, pero el problema fue que escribí:

java -cp C:/java/MyClasses C:/java/MyClasses/utilities/myapp/Cool  

en vez de:

java -cp C:/java/MyClasses utilities/myapp/Cool   

Pensé que el significado de totalmente calificado significaba incluir el nombre de ruta completo en lugar del nombre completo del paquete.

mathewbruens
fuente
He actualizado mi respuesta para tratar de abordar esa confusión.
Stephen C
2
Ninguno de estos es correcto. La clase se debe dar como utilities.myapp.Coolo sea el nombre de su paquete, si lo hay.
Marqués de Lorne
5

Primero configure la ruta con este comando;

set path="paste the set path address"

Entonces necesitas cargar el programa. Escriba "cd (nombre de la carpeta)" en la unidad almacenada y compílelo. Por ejemplo, si mi programa está almacenado en la unidad D, escriba "D:", presione Intro y escriba "cd (nombre de la carpeta)".

arun
fuente
44
Esto no ayuda Esta pregunta es sobre programas Java, no ejecutables ordinarios. Java no utiliza PATH para localizar nada, y si "cd" lo ayuda por suerte y no por juicio.
Stephen C
if "cd" helps then it by luck rather than by judgement. Esto es incorrecto (creo), ya que Java usa el directorio actual .como parte de la ruta de clase por defecto.
GKFX
2
@GKFX: a eso me refiero. A menos que sepa que está utilizando el classpath predeterminado (o un classpath con "."), "Cd" no tendrá ningún efecto. Esta solución funciona más por suerte (es decir, adivinar / esperar que "." Esté en el classpath) que por juicio (es decir, verificar que "." Está en el classpath). Además, eres incorrecto sobre el valor predeterminado. Java usa "." como classpath de forma predeterminada, no como parte de classpath de forma predeterminada.
Stephen C
5

Lo que solucionó el problema en mi caso fue:

Haga clic derecho en el proyecto / clase que desea ejecutar, luego Run As-> Run Configurations. Luego, debe corregir su configuración existente o agregar una nueva de la siguiente manera:

abra la Classpathpestaña, haga clic en el Advanced...botón y luego agregue la bincarpeta de su proyecto.

sintagma
fuente
5

Si usa Maven para compilar el archivo JAR, asegúrese de especificar la clase principal en el archivo pom.xml:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>class name us.com.test.abc.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
Junchen Liu
fuente
4

Este es un caso específico, pero como llegué a esta página buscando una solución y no la encontré, la agregaré aquí.

Windows (probado con 7) no acepta caracteres especiales (como á) en los nombres de clase y paquete. Sin embargo, Linux sí.

Descubrí esto cuando construí un .jarNetBeans e intenté ejecutarlo en la línea de comandos. Se ejecutó en NetBeans pero no en la línea de comando.

GuiRitter
fuente
4

En Windows, coloque .;el valor CLASSPATH al principio.

Los . (punto) significa "buscar en el directorio actual". Esta es una solución permanente.

También puede configurarlo "una vez" con set CLASSPATH=%CLASSPATH%;.. Esto durará mientras su ventana de cmd esté abierta.

Nenad Bulatovic
fuente
1
Este consejo puede o no ayudar. Ayudará si el árbol de clases que contiene las clases en el directorio actual. No lo hará si no lo son. En realidad no haría esto. En su lugar, crearía un script de envoltura de una línea que funcionara independientemente de si el usuario está en el directorio "correcto".
Stephen C
4

Realmente necesitas hacer esto desde la srccarpeta. Allí escribe la siguiente línea de comando:

[name of the package].[Class Name] [arguments]

Digamos que se llama a su clase CommandLine.classy el código se ve así:

package com.tutorialspoint.java;

    /**
     * Created by mda21185 on 15-6-2016.
     */

    public class CommandLine {
        public static void main(String args[]){
            for(int i=0; i<args.length; i++){
                System.out.println("args[" + i + "]: " + args[i]);
            }
        }
    }

Entonces deberías cdir a la carpeta src y el comando que necesitas ejecutar se vería así:

java com.tutorialspoint.java.CommandLine this is a command line 200 -100

Y la salida en la línea de comando sería:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
Miguel. re
fuente
2
Una clase no puede llamarse "CommandLine.class". Eso sería un error de sintaxis de Java. (Lo que quiere decir es que el archivo que contiene la clase compilada se llama "CommandLine.class" ...). El otro problema es que su instrucción de "cd al directorio fuente" solo funciona si compiló el código >> en << el árbol del directorio fuente. Finalmente, si su compilación usó un argumento "-cp", entonces necesita un equivalente cuando se ejecuta.
Stephen C
En mi proyecto tengo la carpeta src y la carpeta bin en la raíz. Tuve que cdentrar srcy luego ejecutar el comando java ../bin com.blah.blah.MyClassque funcionó para mí. Así que gracias por el consejo!
tamj0rd2
3

En Java, cuando a veces ejecuta la JVM desde la línea de comandos utilizando el ejecutable de Java e intenta iniciar un programa desde un archivo de clase con public static void main (PSVM), puede encontrarse con el siguiente error aunque el parámetro classpath la JVM es precisa y el archivo de clase está presente en el classpath:

Error: main class not found or loaded

Esto sucede si el archivo de clase con PSVM no se pudo cargar. Una posible razón para eso es que la clase puede estar implementando una interfaz o extendiendo otra clase que no está en el classpath. Normalmente, si una clase no está en el classpath, el error arrojado indica como tal. Pero, si la clase en uso se extiende o implementa, Java no puede cargar la clase en sí.

Referencia: https://www.computingnotes.net/java/error-main-class-not-found-or-loaded/

Anandaraja Ravi
fuente
1
¿Leíste la respuesta aceptada? ¿Su respuesta agrega algo nuevo?
Stephen C
1
@StephenC He intentado encontrar un motivo en su lista mirando las categorías "Razón" y sus puntos. No pude encontrar el punto de coincidencia en el título "Razón # 1" y "Razón # 2" no se parecía mucho a mi caso (porque estaba seguro de que no hay ningún problema con classpath en sí). He encontrado la razón al realizar experimentos y me sorprendió que en mi caso se mostrara el error "clase principal no encontrada" porque la interfaz de implementación no estaba en la ruta de clase. Claro que puedes decir "deberías leer todo lo descrito en la publicación", pero me parece que tu lista de razones puede mejorarse.
gumkins
3

Al ejecutar el javacon la -cpopción como se anuncia en Windows PowerShell, puede obtener un error similar al siguiente:

The term `ClassName` is not recognized as the name of a cmdlet, function, script ...

Para que PowerShell acepte el comando, los argumentos de la -cpopción deben estar contenidos entre comillas como en:

java -cp 'someDependency.jar;.' ClassName

Formar el comando de esta manera debería permitir que Java procese los argumentos de classpath correctamente.

Chezzwizz
fuente
3

También me enfrenté a errores similares al probar una conexión JDBC Java MongoDB. Creo que es bueno resumir mi solución final en resumen para que en el futuro cualquiera pueda mirar directamente los dos comandos y sea bueno continuar.

Suponga que está en el directorio donde existen su archivo Java y sus dependencias externas (archivos JAR).

Compilar:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - argumento classpath; pasar todos los archivos JAR dependientes uno por uno
  • * .java: este es el archivo de clase Java que tiene el método principal. sdsd

Correr:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Observe los dos puntos (Unix) / coma (Windows) después de que finalicen todos los archivos JAR de dependencia
  • Al final, observe el nombre de la clase principal sin ninguna extensión (sin .class o .java)
khichar.anil
fuente
Todo esto supone que 1) JavaMongoDBConnectionno tiene paquete y 2) no cambia el directorio. Es, por decir lo menos, frágil. Y al no explicar los problemas, llevará a los novatos a probar este enfoque en situaciones en las que no funcionará . En resumen, fomenta las "técnicas de programación de vudú": en.wikipedia.org/wiki/Voodoo_programming
Stephen C
3

Muy bien, ya hay muchas respuestas, pero nadie mencionó el caso en que los permisos de los archivos pueden ser los culpables.

Cuando se ejecuta, un usuario puede no tener acceso al archivo JAR o a uno de los directorios de la ruta. Por ejemplo, considere:

Archivo jar en /dir1/dir2/dir3/myjar.jar

El usuario1 que posee el archivo JAR puede hacer:

# Running as User1
cd /dir1/dir2/dir3/
chmod +r myjar.jar

Pero todavía no funciona:

# Running as User2
java -cp "/dir1/dir2/dir3:/dir1/dir2/javalibs" MyProgram
Error: Could not find or load main class MyProgram

Esto se debe a que el usuario en ejecución (Usuario2) no tiene acceso a dir1, dir2 o javalibs o dir3. Puede volver loco a alguien cuando el Usuario1 puede ver los archivos y puede acceder a ellos, pero el error aún ocurre para el Usuario2.

biocyberman
fuente
2

Recibí este error después de hacer mvn eclipse:eclipse esto desordenó .classpathun poco mi archivo.

Tuve que cambiar las líneas .classpathde

<classpathentry kind="src" path="src/main/java" including="**/*.java"/>
<classpathentry kind="src" path="src/main/resources" excluding="**/*.java"/>

a

<classpathentry kind="src" path="src/main/java" output="target/classes" />
<classpathentry kind="src" path="src/main/resources" excluding="**"  output="target/classes" />
Jaanus
fuente
2

No pude resolver este problema con las soluciones indicadas aquí (aunque la respuesta indicada, sin duda, aclaró mis conceptos). Enfrenté este problema dos veces y cada vez que probé diferentes soluciones (en el IDE de Eclipse).

  • En primer lugar, me he encontrado con múltiples mainmétodos en diferentes clases de mi proyecto. Entonces, había eliminado el mainmétodo de las clases posteriores.
  • En segundo lugar, probé la siguiente solución:
    1. Haga clic derecho en mi directorio principal del proyecto.
    2. Diríjase a la fuente, luego limpie y siga con la configuración predeterminada y en Finalizar. Después de algunas tareas en segundo plano, se lo dirigirá a su directorio principal del proyecto.
    3. Después de eso cierro mi proyecto, lo vuelvo a abrir y, boom, finalmente resolví mi problema.
Anus Kaleem
fuente
1
Eliminar mainmétodos no solucionará el problema. No hay nada técnicamente incorrecto con una aplicación que tiene múltiples puntos de entrada.
Stephen C