O que significa "Não foi possível encontrar ou carregar a classe principal"?

1370

Um problema comum que os novos desenvolvedores Java experimentam é que seus programas falham ao executar com a mensagem de erro: Could not find or load main class ...

O que isso significa, o que causa e como você deve corrigi-lo?

Stephen C
fonte
37
Observe que esta é uma pergunta de "resposta automática" que se destina a ser uma consulta de perguntas e respostas genérica para novos usuários de Java. Não consegui encontrar uma sessão de perguntas e respostas que cubra isso adequadamente (IMO).
Stephen C

Respostas:

1230

A java <class-name>sintaxe do comando

Primeiro de tudo, você precisa entender a maneira correta de iniciar um programa usando o comando java(ou javaw).

A sintaxe normal 1 é esta:

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

onde <option>é uma opção de linha de comando (começando com um caractere "-"), <class-name>é um nome de classe Java totalmente qualificado e <arg>é um argumento arbitrário de linha de comando que é passado para o seu aplicativo.


1 - Existem outras sintaxes descritas no final desta resposta.

O nome totalmente qualificado (FQN) para a classe é convencionalmente escrito como você faria no código-fonte Java; por exemplo

    packagename.packagename2.packagename3.ClassName

No entanto, algumas versões do javacomando permitem usar barras em vez de pontos; por exemplo

    packagename/packagename2/packagename3/ClassName

que (confusamente) se parece com um nome de caminho de arquivo, mas não é um. Observe que o termo nome completo é terminologia Java padrão ... não é algo que acabei de inventar para confundir você :-)

Aqui está um exemplo de como um javacomando deve ser:

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

O exemplo acima fará com que o javacomando faça o seguinte:

  1. Procure a versão compilada da com.acme.example.ListUsersclasse.
  2. Carregue a classe.
  3. Verifique se a classe possui um mainmétodo com assinatura , tipo de retorno e modificadores fornecidos por public static void main(String[]). (Observe que o nome do argumento do método NÃO faz parte da assinatura.)
  4. Chame esse método passando os argumentos da linha de comando ("fred", "joe", "bert") como a String[].

Razões pelas quais o Java não consegue encontrar a classe

Quando você recebe a mensagem "Não foi possível encontrar ou carregar a classe principal ...", isso significa que a primeira etapa falhou. O javacomando não conseguiu encontrar a classe. E, de fato, o "..." na mensagem será o nome completo da classe que você javaestá procurando.

Então, por que não foi possível encontrar a classe?

Razão # 1 - você cometeu um erro com o argumento classname

A primeira causa provável é que você pode ter fornecido o nome de classe errado. (Ou ... o nome certo da classe, mas na forma errada.) Considerando o exemplo acima, aqui estão várias maneiras erradas de especificar o nome da classe:

  • Exemplo # 1 - um nome de classe simples:

    java ListUser

    Quando a classe é declarada em um pacote como com.acme.example, então você deve usar o nome completo da classe, incluindo o nome do pacote no javacomando; por exemplo

    java com.acme.example.ListUser
  • Exemplo # 2 - um nome de arquivo ou nome de caminho em vez de um nome de classe:

    java ListUser.class
    java com/acme/example/ListUser.class
    
  • Exemplo # 3 - um nome de classe com a caixa incorreta:

    java com.acme.example.listuser
  • Exemplo # 4 - um erro de digitação

    java com.acme.example.mistuser
  • Exemplo # 5 - um nome de arquivo de origem (exceto Java 11 ou posterior; veja abaixo)

    java ListUser.java
  • Exemplo # 6 - você esqueceu completamente o nome da classe

    java lots of arguments

Razão # 2 - o caminho de classe do aplicativo está especificado incorretamente

A segunda causa provável é que o nome da classe está correto, mas que o javacomando não pode encontrar a classe. Para entender isso, você precisa entender o conceito de "caminho de classe". Isso é bem explicado pela documentação do Oracle:

Então ... se você especificou o nome da classe corretamente, a próxima coisa a verificar é se você especificou o caminho da classe corretamente:

  1. Leia os três documentos vinculados acima. (Sim ... LEIA-os! É importante que um programador Java entenda pelo menos o básico de como os mecanismos do caminho de classe Java funcionam.)
  2. Observe a linha de comandos e / ou a variável de ambiente CLASSPATH que está em vigor quando você executa o javacomando. Verifique se os nomes dos diretórios e dos arquivos JAR estão corretos.
  3. Se houver nomes de caminho relativos no caminho de classe, verifique se eles foram resolvidos corretamente ... no diretório atual em vigor quando você executa o javacomando.
  4. Verifique se a classe (mencionada na mensagem de erro) pode estar localizada no caminho de classe efetivo .
  5. Observe que a sintaxe do caminho de classe é diferente para Windows e Linux e Mac OS. (O separador de caminho de classe está ;no Windows e :nos outros. Se você usar o separador errado para sua plataforma, não receberá uma mensagem de erro explícita. Em vez disso, receberá um arquivo ou diretório inexistente no caminho que será ignorado silenciosamente. .)

Razão # 2a - o diretório errado está no caminho de classe

Quando você coloca um diretório no caminho de classe, ele corresponde nocionalmente à raiz do espaço para nome qualificado. As classes estão localizadas na estrutura de diretórios abaixo dessa raiz, mapeando o nome completo para um nome de caminho . Por exemplo, se "/ usr / local / acme / classes" estiver no caminho da classe, quando a JVM procurar uma classe chamada com.acme.example.Foon, procurará um arquivo ".class" com este nome de caminho:

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

Se você tivesse colocado "/ usr / local / acme / classes / com / acme / example" no caminho de classe, a JVM não conseguiria encontrar a classe.

Razão # 2b - o caminho do subdiretório não corresponde ao FQN

Se sua classe FQN for com.acme.example.Foon, a JVM procurará "Foon.class" no diretório "com / acme / example":

  • Se sua estrutura de diretórios não corresponder à nomeação do pacote conforme o padrão acima, a JVM não encontrará sua classe.

  • Se você tentar renomear uma classe movendo-a, isso também falhará ... mas o rastreamento de pilha de exceção será diferente. É possível dizer algo como isto:

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

    porque o FQN no arquivo de classe não corresponde ao que o carregador de classes espera encontrar.

Para dar um exemplo concreto, supondo que:

  • você quer dar com.acme.example.Foonaula,
  • o caminho completo do arquivo é /usr/local/acme/classes/com/acme/example/Foon.class,
  • seu diretório de trabalho atual é /usr/local/acme/classes/com/acme/example/,

então:

# 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:

  • A -classpathopção pode ser abreviada -cpna maioria dos releases Java. Verifique as respectivas entradas manuais para java, javace assim por diante.
  • Pense com cuidado ao escolher entre nomes de caminho absolutos e relativos nos caminhos de classe. Lembre-se de que um nome de caminho relativo pode "quebrar" se o diretório atual for alterado.

Razão # 2c - dependências ausentes no caminho de classe

O caminho de classe precisa incluir todas as outras classes (não pertencentes ao sistema) das quais seu aplicativo depende. (As classes do sistema são localizadas automaticamente e você raramente precisa se preocupar com isso.) Para que a classe principal seja carregada corretamente, a JVM precisa localizar:

(Nota: as especificações JLS e JVM permitem algum escopo para uma JVM carregar classes "preguiçosamente" e isso pode afetar quando uma exceção do carregador de classes é lançada.)

Razão # 3 - a classe foi declarada no pacote errado

Ocasionalmente, alguém coloca um arquivo de código-fonte na pasta errada em sua árvore de código-fonte ou deixa de fora a packagedeclaração. Se você fizer isso em um IDE, o compilador do IDE informará sobre isso imediatamente. Da mesma forma, se você usar uma ferramenta decente de construção Java, a ferramenta será executada de javacmaneira a detectar o problema. No entanto, se você criar seu código Java manualmente, poderá fazê-lo de forma que o compilador não perceba o problema e o arquivo ".class" resultante não esteja no local que você espera.

Ainda não encontrou o problema?

Há muitas coisas para verificar e é fácil perder alguma coisa. Tente adicionar a -Xdiagopção à javalinha de comando (como a primeira coisa a seguir java). Ele produzirá várias coisas sobre o carregamento de classes, e isso pode oferecer pistas sobre qual é o verdadeiro problema.

Além disso, considere possíveis problemas causados ​​pela cópia e colagem de caracteres invisíveis ou não ASCII de sites, documentos e assim por diante. E considere "homoglifos", duas letras ou símbolos parecem iguais ... mas não são

Finalmente, você pode aparentemente ter esse problema se tentar iniciar a partir de um arquivo JAR com assinaturas incorretas (META-INF/*.SF).


Sintaxe alternativa para java

Existem três sintaxes alternativas para o lançamento de programas Java usando o java command.

1) A sintaxe usada para iniciar um arquivo JAR "executável" é a seguinte:

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

por exemplo

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

O nome da classe do ponto de entrada (ou seja com.acme.example.ListUser) e o caminho da classe são especificados no MANIFEST do arquivo JAR.

2) A sintaxe para iniciar um aplicativo a partir de um módulo (Java 9 e posterior) é a seguinte:

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

O nome da classe do ponto de entrada é definido por <module>ele mesmo ou é fornecido pelo opcional <mainclass>.

3) A partir do Java 11, você pode compilar e executar um único arquivo de código-fonte e executá-lo com a seguinte sintaxe:

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

onde está (normalmente) um arquivo com o sufixo ".java".

Para mais detalhes, consulte a documentação oficial do javacomando para o release Java que você está usando.


IDEs

Um Java IDE típico tem suporte para executar aplicativos Java na própria JVM IDE ou em uma JVM filha. Eles geralmente são imunes a essa exceção específica, porque o IDE usa seus próprios mecanismos para construir o caminho de classe do tempo de execução, identificar a classe principal e criar a javalinha de comando.

No entanto, ainda é possível que essa exceção ocorra, se você fizer coisas atrás da parte traseira do IDE. Por exemplo, se você configurou anteriormente um Disparador de Aplicativos para seu aplicativo Java no Eclipse e moveu o arquivo JAR que contém a classe "main" para um local diferente no sistema de arquivos sem informar o Eclipse , o Eclipse ativaria involuntariamente a JVM com um caminho de classe incorreto.

Em resumo, se você encontrar esse problema em um IDE, verifique coisas como estado antigo do IDE, referências de projetos ou configurações do iniciador interrompidas.

Também é possível que um IDE simplesmente fique confuso. Os IDE são peças de software extremamente complicadas, que incluem muitas partes em interação. Muitas dessas partes adotam várias estratégias de cache para tornar o IDE como um todo responsivo. Às vezes, isso pode dar errado, e um sintoma possível são problemas ao iniciar aplicativos. Se você suspeitar que isso possa estar acontecendo, vale a pena tentar outras coisas, como reiniciar o IDE, reconstruir o projeto e assim por diante.


Outras referências

Stephen C
fonte
43
Eu tive esse problema quando estava tentando executar uma classe com uma biblioteca de terceiros. Invoquei java como este: java -cp ../third-party-library.jar com.my.package.MyClass; Isso não funciona, em vez disso, é necessário adicionar a pasta local para o caminho da classe, bem como (separados por :, como este: java -cp ../third-party-library.jar:. com.my.package.MyClass, então ele deve funcionar
lanoxx
23
Depois de anos de programação em java, ainda consegui terminar nesta página. Para mim, o problema era que a sintaxe do caminho de classe depende do sistema operacional . Eu sou um pouco iniciante em programação no Windows e não fazia ideia.
Keyser
5
Notas adicionais, ponto 2, me salve! É triste ver que javanão diz que não encontra uma classe importada, mas sim a classe principal que você está tentando executar. Isso é enganador, embora eu tenha certeza de que há uma razão para isso. Eu tive o caso em que javasabia exatamente onde está minha classe, no entanto, ela não conseguiu encontrar uma das classes importadas. Em vez de dizer isso, reclamou de não encontrar minha classe principal. Realmente, irritante.
MSX
Eu tive esse problema duas vezes no Eclipse. Primeira vez que a assinatura de main () estava errada. Na segunda vez que renomeei um arquivo .jar, e mesmo que eu tenha adicionado o novo ao caminho de construção, o Eclipse não encontrou o antigo, portanto o projeto não foi compilado com esse erro. Eu tive que remover o arquivo .jar de Projeto> Propriedades> Caminho de compilação Java> Bibliotecas.
precisa saber é o seguinte
Eu o encontrei pela terceira vez. Executei o programa a partir de um arquivo em lotes do Windows 10 e coloquei o nome .jar em uma variável (chamada com "-cp% jarname%; lib *"). Coloquei por engano um espaço extra no final do jarname, e isso causou o erro. Hat trick :)
GregT
239

Se o seu nome de código fonte for HelloWorld.java, seu código compilado será HelloWorld.class.

Você receberá esse erro se o chamar usando:

java HelloWorld.class

Em vez disso, use o seguinte:

java HelloWorld
pano de fundo
fonte
3
O problema é que esta solução funciona apenas para classes Java declaradas no pacote padrão sem dependências de arquivo JAR. (E mesmo assim, nem sempre.) A maioria dos programas Java não é tão simples.
Stephen C
1
como Stephen disse, isso funciona apenas com "pacote padrão" - o que significa que não há declaração de pacote na parte superior do arquivo. Para um teste rápido de algum código, fiz: javac TestCode.javaseguido porjava TestCode
Alguém em algum lugar
Isto não funcionou para mim. Ele ainda diz: "Não foi possível localizar ou carregar HelloWorld classe principal"
Jim
java -jar HelloWorld.jar também é uma opção
BMaximus 7/16
12
Eu precisava fazerjava -classpath . HelloWorld
Chris Prince
136

Se suas classes estiverem em pacotes , você deverá cdacessar o diretório raiz do seu projeto e executar usando o nome completo da classe (packageName.MainClassName).

Exemplo:

Minhas aulas estão aqui:

D:\project\com\cse\

O nome completo da minha classe principal é:

com.cse.Main

Então, cdvolto ao diretório raiz do projeto:

D:\project

Em seguida, emita o javacomando:

java com.cse.Main

Esta resposta é para resgatar os programadores iniciantes em Java da frustração causada por um erro comum. Recomendamos que você leia a resposta aceita para obter um conhecimento mais profundo sobre o caminho de classe java.

tharinduwijewardane
fonte
2
Essa resposta faz um monte de suposições. E há outras maneiras de conseguir isso. Em vez de seguir cegamente o conselho acima, recomendo que as pessoas leiam os links na minha resposta que explicam como o caminho de classe Java funciona. É melhor para entender o que você está fazendo ...
Stephen C
2
Esta resposta faz as suposições exatas que eu precisava :) Eu estava localizado no diretório do arquivo .class e o java.exe não estava funcionando. Uma vez que eu fiz o cd acima e executei com o nome do pacote incluído na linha de comando, ele funcionou.
Nick Constantine
61

Se você definir a classe principal e o método principal em apackage , deverá executá-lo no diretório hierárquico, usando o nome completo da classe ( packageName.MainClassName).

Suponha que haja um arquivo de código fonte (Main.java):

package com.test;

public class Main {

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

Para executar este código, você deve colocar Main.Classno pacote como diretório ./com/test/Main.Java. E no diretório raiz use java com.test.Main.

M-Razavi
fonte
1
Veja "Notas adicionais nº 1" da minha resposta. Para uma melhor explicação desse problema.
Stephen C
14
@StephenC Sim, sua resposta é mais completa (e, é claro, +1), mas essa resposta específica continha a palavra "pacote", o que me permitiu encontrar o que precisava rapidamente. E funcionou. Então, +1 Razavi. StephenC, o seu não possui o exemplo simples de pacote que eu precisava, pois sou novo em Java.
kmort
5
Este foi exatamente o meu problema. Eu tenho vasculhado toneladas de documentos em Java e este exemplo concreto é o que eu precisava #
John
1
Sim, um exemplo concreto é bom, isso funcionou perfeitamente. Tenho certeza de que a resposta principal é muito completa, mas foi difícil ver a árvore para a floresta. @Razavi
Pixel #
1
Eu gosto desta resposta mais curta e útil, em vez de uma resposta aceita!
Spara 18/04/19
46

Quando o mesmo código funciona em um PC, mas mostra o erro em outro, a melhor solução que eu já encontrei é compilar da seguinte maneira:

javac HelloWorld.java
java -cp . HelloWorld
Enamul Hassan
fonte
2
Esta não é uma boa recomendação. Você está dependendo da variável de ambiente CLASSPATH estar desativada ou ter um valor consistente com ".". Sim, funciona em muitos casos, mas não em outros.
Stephen C
Bem, certamente javac -classpath . HelloWorld.javateria funcionado! E essa é uma solução melhor no seu caso.
Stephen C
2
Se você tiver o 'pacote com.some.address' como primeira linha - isso não funcionará. Você vai precisar para comentar 'endereço pacote' ..
Joe
1
@ Joe - Esse hack (comentando o pacote) funcionará (em alguns casos), mas é uma má idéia. Uma idéia melhor é aprender / entender o que causou o problema e implementar a solução correta.
Stephen C
36

O que me ajudou foi especificar o caminho de classe na linha de comando, por exemplo:

  1. Criar uma nova pasta, C:\temp

  2. Crie o arquivo Temp.java em C:\temp, com a seguinte classe:

    public class Temp {
        public static void main(String args[]) {
            System.out.println(args[0]);
        }
    }
  3. Abra uma linha de comando na pasta C:\tempe escreva o seguinte comando para compilar a classe Temp:

    javac Temp.java
  4. Execute a classe Java compilada, incluindo a -classpathopção para informar ao JRE onde encontrar a classe:

    java -classpath C:\temp Temp Hello!
Celebridades
fonte
3
No Ubuntu, eu também tive que especificar o caminho. Não entenda por que ele não pode usar o Diretório de Trabalho Atual por padrão. Estou convencido de que o Java é patrocinado pelos fabricantes de teclados !!
foi
1
@ ido - A razão que "." não está em $ PATH por padrão é que é uma armadilha de segurança. seas.upenn.edu/cets/answers/dot-path.html
Stephen C
Muito obrigado por isso ...... apesar de não saber por que o java não estava conseguindo descobrir o caminho de classe, mesmo depois de defini-lo nas variáveis ​​de ambiente.
Akash89
@ akash89 - Os motivos mais prováveis ​​foram: 1) javanão estava olhando para $ CLASSPATH (porque você usou -classpath ou -jar) ou 2) a configuração do caminho de classe não foi definida no ambiente que não estava em vigor no contexto em que javaestava. corre; por exemplo, porque você não "originou" o arquivo onde adicionou os comandos setenv no shell direito.
Stephen C
Ainda recebi o erro: Não foi possível encontrar ou carregar a classe principal Temp alguém poderia ajudar!
Star
27

De acordo com a mensagem de erro ("Não foi possível encontrar ou carregar a classe principal"), existem duas categorias de problemas:

  1. Não foi possível encontrar a classe principal
  2. Não foi possível carregar a classe principal (este caso não é totalmente discutido na resposta aceita)

Não foi possível encontrar a classe principal quando há erro de digitação ou sintaxe incorreta no nome completo da classe ou ela não existe no caminho de classe fornecido .

Não foi possível carregar a classe principal quando a classe não pode ser iniciada , normalmente a classe principal estende outra classe e essa classe não existe no caminho de classe fornecido.

Por exemplo:

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

Se a mola de camelo não estiver incluída, esse erro será relatado.

Xiao Peng - ZenUML.com
fonte
"Basicamente" também existem muitas outras categorias. E o problema da superclasse ausente é um subcaso muito incomum. (Tão incomum que eu nunca vi isso ... em perguntas feitas neste site.)
Stephen C
Existem DOIS porque o erro diz "Não foi possível ENCONTRAR ou CARREGAR classe principal". Se houver outras categorias, informe-me. Eu já vi isso, então só quero compartilhá-lo aqui, talvez alguém mais precise.
Xiao Peng - ZenUML.com
1
Eu o revisaria para algo como "Você precisa incluir todas as classes necessárias para iniciar a classe principal para evitar esse erro específico". Não estou tentando convencê-lo. É apenas uma maneira que eu gostaria de ver. Deixei a resposta aqui apenas para pessoas que podem gostar de ler as coisas dessa maneira. Não vamos estender mais essa discussão :) Alterei minha declaração para "não totalmente discutida na resposta aceita" e espero que você se sinta melhor.
Xiao Peng - ZenUML.com
5
Esta informação é crucial e merece uma menção explícita (esta é a única resposta que menciona extends). Acabei de aprender da maneira mais difícil que quando a classe principal falha ao carregar porque estende outra que não pôde ser encontrada , o java não informa qual classe real não foi encontrada (diferente NoClassDefFoundError). Então, sim, isso acontece, e é uma situação arrepiante quando você não sabe disso.
Hugues M.
1
Nessa situação, há alguma maneira de dizer exatamente qual classe de dependência está falhando ao carregar?
Carlos A. Ibarra
16

Eu tive um erro nesse caso:

java -cp lib.jar com.mypackage.Main

Funciona com o ;Windows e o :Unix:

java -cp lib.jar; com.mypackage.Main
Yamahar1sp
fonte
Sim. Provavelmente, isso Mainnão está no arquivo JAR. -cp lib.jar;significa a mesma coisa que, por exemplo, -cp lib.jar;. o diretório atual está incluído no caminho de classe.
Stephen C
Finalmente corrigiu o problema para unix .. Obrigado (funciona com :)
Vicky
16

Tente -Xdiag .

A resposta de Steve C cobre bem os casos possíveis, mas às vezes determinar se a classe não foi encontrada ou carregada pode não ser tão fácil. Use java -Xdiag(desde o JDK 7). Isso imprime um bom rastreamento de pilha, que fornece uma dica sobre o Could not find or load main classsignificado da mensagem.

Por exemplo, ele pode indicar outras classes usadas pela classe principal que não foram encontradas e impediu o carregamento da classe principal.

jan.supol
fonte
16

Use este comando:

java -cp . [PACKAGE.]CLASSNAME

Exemplo: Se o seu nome de classe for Hello.class criado a partir do Hello.java, use o comando abaixo:

java -cp . Hello

Se o seu arquivo Hello.java estiver dentro do pacote com.demo, use o comando abaixo

java -cp . com.demo.Hello

Com o JDK 8, muitas vezes acontece que o arquivo de classe está presente na mesma pasta, mas o javacomando espera classpath e, por esse motivo, adicionamos -cp .a pasta atual como referência para classpath.

shaILU
fonte
Isso funciona apenas em casos simples. Casos mais complicados requerem um caminho de classe mais complicado.
Stephen C
E, para casos realmente simples, -cp .é desnecessário, porque se $CLASSPATHnão estiver definido, .será o caminho de classe padrão.
Stephen C
Não, Stephen, muitas vezes no caminho de classe padrão do Windows não funciona. Eu experimentei em três máquinas diferentes, você pode experimentar também.
shaILU 5/05
Provavelmente, você deve ter definido a variável de ambiente% CLASSPATH% em algum lugar. Se você fizer isso, não estará usando o caminho de classe padrão. (O que é echo %CLASSPATH%gerado?) E não, não consigo verificar porque não tenho um PC com Windows.
Stephen C
2
Isso funcionou para mim quando eu tentei executar um programa simples de linha de comando
SnuKies
15

Às vezes, o que pode estar causando o problema não tem nada a ver com a classe principal, e eu tive que descobrir isso da maneira mais difícil. Foi uma biblioteca referenciada que eu mudei e me deu o:

Não foi possível encontrar ou carregar a classe principal xxx Linux

Acabei de excluir essa referência, adicionei-a novamente e funcionou bem novamente.

Eduardo Dennis
fonte
1
Parece que o problema era que você tinha um caminho de classe incorreto devido a uma "referência" quebrada no seu projeto no seu IDE. Vou atualizar minha resposta para cobrir esse caso.
Stephen C
@StephenC e EduardoDennis, Também aqui também havia um jarro ausente, que continha uma interface na qual a classe principal dependia para ser instanciada. Portanto, a mensagem de erro é muito ampla. Devo dizer "não foi possível encontrar" se o arquivo de classe não foi encontrado e "não foi possível carregar (falta de dependências)" se houver algo faltando, mas não o próprio arquivo, portanto, a mensagem de erro sendo muito ampla será enganosa se você se concentrar apenas na parte "encontrar" :(
Aquarius Power
@AquariusPower - Deveria haver um rastreamento de pilha "causado por" adicional para a exceção "cause" que dizia que a classe estava faltando. Se você deseja sugerir aos desenvolvedores Java que eles alterem uma mensagem de erro que diz que há mais de 20 anos ... fique à vontade. (Acho que a mensagem de erro está correta O problema era que >> você << estreitou-se em na cláusula errada..)
Stephen C
@StephenC, o que eu quis dizer é que eles certamente têm acesso às informações se o arquivo da classe principal estiver disponível ou não, então por que não nos mostrar uma mensagem de erro melhor dizendo que esse arquivo está ausente? Por outro lado, eles também poderiam dizer "O arquivo foi encontrado, mas não pôde ser carregado" naquele momento, focaríamos imediatamente as dependências, em vez de perdermos meio dia pesquisando e testando coisas para entender. Só que eu quis dizer :). Eles podem fazê-lo de maneira limitada por mais de 20 anos, mas podem melhorá-lo e estamos aqui para garantir que isso aconteça através de nossas críticas e reclamações! : D
Aquarius Power
Por favor, entenda o que eu >> significava. Reclamar sobre isso em algum comentário obscuro sobre as perguntas e respostas de 3 anos não vai conseguir nada. As pessoas que podem agir de maneira inacreditável em suas reclamações não perceberão. Se você quiser fazer algo construtivo, envie um patch. (Eu não avaliar suas chances, mas será maior do que se você apenas whinge sobre isso.)
Stephen C
10

Neste exemplo, você tem:

Não foi possível encontrar ou carregar a classe principal ?

É porque você está usando "-classpath", mas o traço não é o mesmo usado javano prompt de comando. Eu tive esse problema ao copiar e colar do bloco de notas para o cmd.

Nathan Williams
fonte
2
Uau! Essa é uma causa totalmente bizarra! (Mas serve-lhe direito para usar o bloco de notas, em vez de um editor de texto reais :-))
Stephen C
10

Eu tive o mesmo problema e finalmente encontrei meu erro :) Eu usei este comando para compilar e funcionou corretamente:

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

Mas este comando não funcionou para mim (não consegui encontrar ou carregar a classe 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, acabei de adicionar o caractere ':' no final do caminho de classe e o problema foi resolvido:

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
fonte
7

No meu caso, o erro apareceu porque eu havia fornecido o nome do arquivo de origem em vez do nome da classe.

Precisamos fornecer o nome da classe que contém o método principal para o intérprete.

KawaiKx
fonte
Sim. Veja meu exemplo # 2 das maneiras erradas de especificar o nome da classe !!
Stephen C
7

Isso pode ajudá-lo se o seu caso for especificamente como o meu: como iniciante, também encontrei esse problema ao tentar executar um programa Java.

Eu compilei assim:

javac HelloWorld.java

E tentei rodar também com a mesma extensão:

java Helloworld.java

Quando removi .javae reescrevi o comando java HelloWorld, o programa funcionou perfeitamente. :)

Ramesh Pareek
fonte
2
Isso ocorre porque você está executando a versão compilada do seu .java. Na verdade, ele está executando o arquivo .class
Jason V
Para que conste, isso é o mesmo que a Razão # 1, Exemplo # 5 na minha resposta ...
Stephen C
6

Todas as respostas aqui são direcionadas aos usuários do Windows, ao que parece. Para Mac, o separador de caminho de classe é :, não ;. Como um erro ao definir o caminho de classe usando; não é exibido, pode ser difícil descobrir se ele vem do Windows para o Mac.

Aqui está o comando Mac correspondente:

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

Onde neste exemplo o pacote está com.teste uma libpasta também deve ser incluída no caminho de classe.

céu azul
fonte
2
No Linux, assim como no Mac.
precisa saber é o seguinte
Por que /*é necessário?
precisa saber é o seguinte
É uma sintaxe curinga. (Não é obrigatório Você pode listar explicitamente os JARs se você quiser..)
Stephen C
6

insira a descrição da imagem aqui

Local do arquivo de classe: C: \ test \ com \ company

Nome do arquivo: Main.class

Nome completo da classe: com.company.Main

Comando da linha de comando:

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

Observe aqui que o caminho da classe NÃO inclui \ com \ company

developer747
fonte
6

Passei um tempo decente tentando resolver esse problema. Eu pensei que estava de alguma forma configurando meu caminho de classe incorretamente, mas o problema foi que eu digitei:

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

ao invés de:

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

Eu pensei que o significado de totalmente qualificado pretendia incluir o nome completo do caminho em vez do nome completo do pacote.

mathewbruens
fonte
Atualizei minha resposta para tentar resolver essa confusão.
Stephen C
2
Nenhuma delas está correta. A classe deve ser fornecida como utilities.myapp.Coolou seja o nome do pacote, se houver.
Marquês de Lorne
5

Primeiro defina o caminho usando este comando;

set path="paste the set path address"

Então você precisa carregar o programa. Digite "cd (nome da pasta)" na unidade armazenada e compile-a. Por exemplo, se meu programa estiver armazenado na unidade D, digite "D:" pressione enter e digite "cd (nome da pasta)".

uma corrida
fonte
4
Isso não ajuda. Esta pergunta é sobre programas Java, não executáveis ​​comuns. O Java não usa PATH para localizar nada, e se "cd" o ajudar, por sorte e não por julgamento.
Stephen C
if "cd" helps then it by luck rather than by judgement. Isso está errado (eu acredito), pois o java usa o diretório atual .como parte do caminho de classe por padrão.
GKFX 31/03
2
@GKFX - É o que quero dizer. A menos que você saiba que está usando o caminho de classe padrão (ou um caminho de classe com "."), "Cd" não terá efeito. Essa solução funciona mais por sorte (ou seja, adivinhando / esperando que "." Esteja no caminho de classe) do que por julgamento (ou seja, verificando se "." Está no caminho de classe). Além disso, você está incorreto sobre o padrão. Java usa "." como o caminho de classe por padrão, não como parte do caminho de classe por padrão.
Stephen C
5

O que corrigiu o problema no meu caso foi:

Clique com o botão direito do mouse no projeto / classe que deseja executar e, em seguida Run As->Run Configurations . Em seguida, você deve corrigir sua configuração existente ou adicionar novo da seguinte maneira:

abra a Classpathguia, clique no Advanced...botão e adicione a binpasta do seu projeto.

sintagma
fonte
5

Se você usar o Maven para criar o arquivo JAR, especifique a classe principal no arquivo 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
fonte
4

Este é um caso específico, mas como cheguei a esta página procurando uma solução e não a encontrei, vou adicioná-la aqui.

O Windows (testado com 7) não aceita caracteres especiais (como á ) nos nomes de classe e pacote. O Linux, no entanto.

Eu descobri isso quando criei um .jarno NetBeans e tentei executá-lo na linha de comando. Ele foi executado no NetBeans, mas não na linha de comando.

GuiRitter
fonte
4

No Windows, coloque .;o valor CLASSPATH no início.

O . (ponto) significa "procurar no diretório atual". Esta é uma solução permanente.

Além disso, você pode configurá-lo "uma vez" com o conjunto CLASSPATH=%CLASSPATH%;.. Isso durará enquanto a janela do cmd estiver aberta.

Nenad Bulatovic
fonte
1
Este conselho pode ou não ajudar. Ajudará se a árvore de classes que contém as classes no diretório atual. Não vai se não forem. Na verdade, eu não faria isso. Em vez disso, eu criaria um script de wrapper de uma linha que funcionasse se o usuário estivesse ou não no diretório "certo".
Stephen C
4

Você realmente precisa fazer isso a partir da srcpasta Lá você digita a seguinte linha de comando:

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

Digamos que sua classe seja chamada CommandLine.classe o código fique assim:

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]);
            }
        }
    }

Em seguida, você deve cdir para a pasta src e o comando que você precisa executar terá a seguinte aparência:

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

E a saída na linha de comando seria:

args[0]: this
args[1]: is
args[2]: a
args[3]: command
args[4]: line
args[5]: 200
args[6]: -100
Mike. D
fonte
2
Uma classe não pode ser chamada "CommandLine.class". Isso seria um erro de sintaxe Java. (O que você quer dizer é que o arquivo que contém a classe compilada é chamado "CommandLine.class" ...). O outro problema é que sua instrução para "cd no diretório de origem" funcionará apenas se você compilar o código >> na << árvore de diretórios de origem. Finalmente, se sua compilação usou um argumento "-cp", você precisará de um equivalente ao executar.
Stephen C
No meu projeto, tenho a pasta src e a pasta bin na raiz. Eu tive que cdentrar srce executar o comando java ../bin com.blah.blah.MyClassque funcionou para mim. Então, obrigado pela dica!
tamj0rd2
3

Em Java, quando você executa a JVM às vezes na linha de comando usando o executável java e está tentando iniciar um programa a partir de um arquivo de classe com PSVM (public static void main), pode ocorrer o erro abaixo, mesmo que o parâmetro classpath para a JVM é precisa e o arquivo de classe está presente no caminho de classe:

Error: main class not found or loaded

Isso acontece se o arquivo de classe com PSVM não puder ser carregado. Uma razão possível para isso é que a classe pode estar implementando uma interface ou estendendo outra classe que não está no caminho de classe. Normalmente, se uma classe não estiver no caminho de classe, o erro gerado indica como tal. Mas, se a classe em uso for estendida ou implementada, o java não poderá carregar a própria classe.

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

Anandaraja Ravi
fonte
1
Você leu a resposta aceita? Sua resposta adiciona algo novo?
Stephen C
1
@StephenC Tentei encontrar um motivo na sua lista examinando as categorias "Motivo" e seus pontos. Não consegui encontrar o ponto correspondente nos títulos "Motivo nº 1" e "Motivo nº 2" não pareciam muito próximos do meu caso (porque eu tinha certeza de que não havia nenhum problema com o caminho de classe). Eu descobri o motivo realizando experimentos e fiquei surpreso que, no meu caso, o erro "classe principal não encontrada" fosse mostrado porque a interface de implementação não estava no caminho da classe. Claro que você pode dizer "você deve ler tudo descrito no post", mas parece-me que sua lista de motivos pode ser melhorada.
gumkins
3

Ao executar o javacom a -cpopção conforme anunciado no Windows PowerShell, você pode receber um erro parecido com:

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

Para que o PowerShell aceite o comando, os argumentos da -cpopção devem estar entre aspas, como em:

java -cp 'someDependency.jar;.' ClassName

A formação do comando dessa maneira deve permitir que o Java processe os argumentos do caminho de classe corretamente.

Chezzwizz
fonte
3

Também enfrentei erros semelhantes ao testar uma conexão Java MongoDB JDBC. Eu acho que é bom resumir minha solução final em resumo, para que, no futuro, qualquer um possa analisar diretamente os dois comandos e seja bom prosseguir.

Suponha que você esteja no diretório em que seu arquivo Java e dependências externas (arquivos JAR) existem.

Compilar:

javac -cp mongo-java-driver-3.4.1.jar JavaMongoDBConnection.java
  • -cp - argumento classpath; passar todos os arquivos JAR dependentes um por um
  • * .java - Este é o arquivo de classe Java que possui o método principal. sdsd

Corre:

java -cp mongo-java-driver-3.4.1.jar: JavaMongoDBConnection
  • Observe os dois pontos (Unix) / vírgula (Windows) depois que todos os arquivos JAR de dependência terminarem
  • No final, observe o nome da classe principal sem nenhuma extensão (sem .class ou .java)
khichar.anil
fonte
Isso tudo pressupõe que 1) JavaMongoDBConnectionnão possui pacote e 2) você não altera o diretório. É, para dizer o mínimo, frágil. E, ao não explicar os problemas, levará os novatos a tentar essa abordagem em situações em que não funcionará . Em resumo, incentiva "técnicas de programação de vodu": en.wikipedia.org/wiki/Voodoo_programming
Stephen C
3

Tudo bem, já existem muitas respostas, mas ninguém mencionou o caso em que as permissões de arquivo podem ser as culpadas.

Ao executar, um usuário pode não ter acesso ao arquivo JAR ou a um dos diretórios do caminho. Por exemplo, considere:

Arquivo jar em /dir1/dir2/dir3/myjar.jar

O usuário1 que possui o arquivo JAR pode:

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

Mas ainda não funciona:

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

Isso ocorre porque o usuário em execução (Usuário2) não tem acesso a dir1, dir2 ou javalibs ou dir3. Isso pode deixar alguém louco quando o Usuário1 pode ver os arquivos e pode acessá-los, mas o erro ainda ocorre no Usuário2.

biocibernético
fonte
2

Eu recebi esse erro depois de fazer mvn eclipse:eclipse Isso atrapalhou .classpathum pouco meu arquivo.

Teve que mudar as linhas .classpathde

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

para

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

Não consegui resolver esse problema com as soluções indicadas aqui (embora a resposta indicada tenha, sem dúvida, esclarecido meus conceitos). Eu enfrentei esse problema duas vezes e cada vez que tentei soluções diferentes (no Eclipse IDE).

  • Em primeiro lugar, me deparei com vários mainmétodos em diferentes classes do meu projeto. Então, eu apaguei omain método das classes subseqüentes.
  • Em segundo lugar, tentei a seguinte solução:
    1. Clique com o botão direito do mouse no meu diretório principal de projeto.
    2. Vá para a fonte, limpe e siga as configurações padrão e em Concluir. Após algumas tarefas em segundo plano, você será direcionado para o diretório principal do projeto.
    3. Depois disso, encerro meu projeto, reabri-o e bato, finalmente resolvi meu problema.
Anus Kaleem
fonte
1
A exclusão de mainmétodos não solucionará o problema. Não há nada tecnicamente errado com um aplicativo que tenha vários pontos de entrada.
Stephen C