Causas da obtenção de um java.lang.VerifyError


191

Estou investigando o seguinte java.lang.VerifyError

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMonthData signature: (IILjava/util/Collection;Ljava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageRe˜̴Mt̴MÚw€mçw€mp:”MŒŒ
                at java.lang.Class.getDeclaredConstructors0(Native Method)
                at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
                at java.lang.Class.getConstructor0(Class.java:2671)

Ocorre quando o servidor jboss no qual o servlet está implementado é iniciado. É compilado com o jdk-1.5.0_11 e tentei recompilar com o jdk-1.5.0_15 sem êxito. Essa é a compilação que funciona bem, mas quando implantada, o java.lang.VerifyError ocorre.

Quando mudei o nome do método e recebi o seguinte erro:

java.lang.VerifyError: (class: be/post/ehr/wfm/application/serviceorganization/report/DisplayReportServlet, method: getMD signature: (IILjava/util/Collection;Lj    ava/util/Collection;Ljava/util/HashMap;Ljava/util/Collection;Ljava/util/Locale;Lorg/apache/struts/util/MessageResources ØÅN|ØÅNÚw€mçw€mX#ÖM|XÔM
            at java.lang.Class.getDeclaredConstructors0(Native Method)
            at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357
            at java.lang.Class.getConstructor0(Class.java:2671)
            at java.lang.Class.newInstance0(Class.java:321)
            at java.lang.Class.newInstance(Class.java:303)

Você pode ver que mais da assinatura do método é mostrada.

A assinatura real do método é

  private PgasePdfTable getMonthData(int month, int year, Collection dayTypes,
                          Collection calendarDays,
                          HashMap bcSpecialDays,
                          Collection activityPeriods,
                          Locale locale, MessageResources resources) throws   Exception {

Eu já tentei olhar para ele javape isso dá a assinatura do método como deveria ser.

Quando meus outros colegas conferem o código, compilam e implantam, eles têm o mesmo problema. Quando o servidor de compilação pega o código e o implementa nos ambientes de desenvolvimento ou teste (HPUX), o mesmo erro ocorre. Além disso, uma máquina de teste automatizada executando o Ubuntu mostra o mesmo erro durante a inicialização do servidor.

O restante do aplicativo é executado corretamente, apenas esse servlet está com defeito. Qualquer idéia para onde procurar seria útil.


1
Eu entendi usando a versão errada do ComparisonFailure. Demorou muito para encontrar ... que foi doloroso
Tim Boland

1
Eu o peguei ao usar a execução instantânea no Android studio (hotswapping na compilação). Desligá-lo fez o trabalho.
Serge

Respostas:


188

java.lang.VerifyError pode ser o resultado quando você compilou em uma biblioteca diferente da que está usando no tempo de execução.

Por exemplo, isso aconteceu comigo ao tentar executar um programa que foi compilado no Xerces 1, mas o Xerces 2 foi encontrado no caminho de classe. As classes necessárias (no org.apache.*espaço para nome) foram encontradas no tempo de execução, portanto nãoClassNotFoundException foi o resultado. Houve alterações nas classes e métodos, de modo que as assinaturas de método encontradas no tempo de execução não correspondiam ao que havia no tempo de compilação.

Normalmente, o compilador sinalizará problemas onde as assinaturas de método não coincidem. A JVM verificará o bytecode novamente quando a classe for carregada e será lançada VerifyErrorquando o bytecode estiver tentando fazer algo que não deveria ser permitido - por exemplo, chamar um método que retorne Stringe depois armazene esse valor de retorno em um campo que contenha a List.


3
Uma coisa a acrescentar: às vezes, a culpa é do IDE ou do dispositivo em que o bytecode não está certo. Tente reiniciar o IDE para que ele reconheça o problema de sincronização. Falha ao excluir e reinstalar o aplicativo. Reiniciar o dispositivo também pode ajudar.
ima747

2
Para descobrir qual classe é a culpada, adicione o argumento da VM -verbose:classe, em seguida, procure a classe imediatamente antes do carregamento java.lang.VerifyError. Isso terá o caminho para o JAR. Use javape compare isso com a classe na qual você está compilando. Achei isso útil, pois a classe relatada no erro não era a causa, na verdade, era um dos argumentos.
steinybot

21

java.lang.VerifyError são os piores.

Você obteria esse erro se o tamanho do bytecode do seu método exceder o limite de 64kb; mas você provavelmente teria notado isso.

Você tem 100% de certeza de que essa classe não está presente no caminho de classe em outro lugar do seu aplicativo, talvez em outro jar?

Além disso, no seu rastreamento de pilha, a codificação de caracteres do arquivo de origem ( utf-8?) Está correta?


Tenho certeza de que não está presente em outro lugar. São 43Kb, ainda é uma classe grande.
Jeroen Wyseur 23/09/08

Obrigado por esse post, no meu caso, era uma codificação diferente: os arquivos JasperReports XMl salvam uma codificação e uma versão java, você deve definir isso de acordo com as configurações do seu projeto (via iReport). Esse foi o problema aqui, obrigado pela sua idéia com a codificação! :)
Tobias

Este foi o meu problema para testes do Android, corrigido multidexing.
Prakash Nadar

10

Como Kevin Panko disse, é principalmente por causa da mudança de biblioteca. Portanto, em alguns casos, uma "limpeza" do projeto (diretório) seguida por uma compilação faz o truque.


9

Uma coisa que você pode tentar é usar o -Xverify:allque verificará o bytecode durante o carregamento e, às vezes, fornecerá mensagens de erro úteis se o bytecode for inválido.



8

VerifyError significa que o arquivo de classe contém um bytecode que está sintaticamente correto, mas viola algumas restrições semânticas, por exemplo, um destino de salto que atravessa os limites do método.

Basicamente, um VerifyError só pode ocorrer quando há um erro do compilador ou quando o arquivo de classe é corrompido de alguma outra maneira (por exemplo, devido a RAM defeituosa ou HD com falha).

Tente compilar com uma versão diferente do JDK e em uma máquina diferente.



4

Eu estava recebendo esse problema devido ao pack200 manipular um arquivo de classe. Um pouco de pesquisa aumentou esse bug do java . Basicamente, a configuração --effort=4fez com que o problema desaparecesse.

Usando o java 1.5.0_17 (embora tenha surgido em todas as variantes do java 1.5 que eu experimentei).


3

Corrigi um problema semelhante ao java.lang.VerifyError, substituindo

        catch (MagickException e)

com

        catch (Exception e)

onde MagickExceptionfoi definido em um projeto de biblioteca (no qual meu projeto tem uma dependência).

Depois disso, recebi uma java.lang.NoClassDefFoundErroraula sobre a mesma biblioteca (corrigida de acordo com https://stackoverflow.com/a/9898820/755804 ).


1
Isso funcionou para mim ... Eu realmente gostaria de descobrir qual foi o erro além de "me substituir por uma exceção geral e eu vou trabalhar".
Alex Hart

@AlexHart é para Android, mas provavelmente a mesma lógica se aplicaria para a empresa Java: stackoverflow.com/a/36814155/253468
TWiStErRob


2

No meu caso, tive que remover este bloco:

compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
}

Ele estava mostrando um erro próximo à Fragment.showDialog()chamada do método.


2

Exemplo mínimo que gera o erro

Uma possibilidade simples é usar o Jasmin ou editar manualmente o bytecode com um editor de arquivo binário.

Vamos criar o voidmétodo sem uma returninstrução (gerada pela return;instrução em Java), que a JVMS diz ser ilegal.

Em Jasmin, poderíamos escrever:

.class public Main
.super java/lang/Object

.method public static main([Ljava/lang/String;)V
   aload_0 ; Just so that we won't get another verify error for empty code.
.end method

Em seguida, fazemos javac Main.je javap -v Maindiz que compilamos:

public static void main(java.lang.String[]);
  descriptor: ([Ljava/lang/String;)V
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0

então realmente não há instruções de retorno.

Agora, se tentarmos executar java Main, obtemos:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.VerifyError: (class: NoReturn, method: main signature: ([Ljava/lang/String;)V) Falling off the end of the code
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
        at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
        at java.lang.Class.getMethod0(Class.java:3018)
        at java.lang.Class.getMethod(Class.java:1784)
        at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)

Esse erro nunca pode ocorrer normalmente em Java, pois o compilador Java adiciona um implícito returnaos voidmétodos para nós. É por isso que não precisamos adicionar a returnaos nossos mainmétodos. Você pode verificar isso com javap.

JVMS

VerifyError acontece quando você tenta executar certos tipos de arquivo de classe ilegal, conforme especificado pelo JVMS 7, capítulo 4.5

A JVMS diz que, quando Java carrega um arquivo, ele deve executar uma série de verificações para verificar se o arquivo de classe está OK antes de executá-lo.

Esses erros não podem ser gerados em um único ciclo de compilação e execução de código Java, porque o JVMS 7 4.10 diz :

Mesmo que um compilador para a linguagem de programação Java deva apenas produzir arquivos de classe que satisfaçam todas as restrições estáticas e estruturais [...]

Portanto, para ver um exemplo de falha mínima, precisaremos gerar o código fonte sem javac.


1

Esta página pode fornecer algumas dicas - http://www.zanthan.com/itymbi/archives/000337.html

Pode haver um bug sutil no corpo desse método que o javac não consiga detectar. Difícil de diagnosticar, a menos que você publique todo o método aqui.

Você pode começar declarando o maior número possível de variáveis ​​como final ... isso teria detectado o bug mencionado no site zanthan e, geralmente, é uma boa prática.


1
Esse cara atingiu um bug do compilador em 2002, mas esse bug foi corrigido desde então.
precisa

1

Bem, no meu caso, meu projeto A dependia de outro, digamos X (A estava usando algumas das classes definidas em X). Então, quando adicionei o X como um projeto de referência no caminho de construção de A, recebi esse erro. No entanto, quando removi o X como o projeto referenciado e incluí o frasco do X como uma das bibliotecas, o problema foi resolvido.


1

Verifique se há várias versões do mesmo arquivo jar no seu caminho de classe.

Por exemplo, eu tinha o opennlp-tools-1.3.0.jar e o opennlp-tools-1.5.3.jar no meu caminho de classe e obtive esse erro. A solução foi excluir o opennlp-tools-1.3.0.jar.



1

Outro motivo para esse erro pode ser a combinação de AspectJ <= 1.6.11 com JRE> 6.

Consulte o Eclipse Bug 353467 e o bilhete Kieker 307 para obter detalhes.

Isso é especialmente verdade quando tudo funciona bem no JRE 6 e a mudança para o JRE7 quebra as coisas.


1

Isso também pode acontecer quando você tem muitas importações de módulos com o maven. Haverá duas ou mais classes com exatamente o mesmo nome (mesmo nome qualificado). Este erro é resultante da diferença de interpretação entre o tempo de compilação e o tempo de execução.


1

Se você estiver migrando para o java7 ou usando o java7, geralmente esse erro pode ser visto. Eu enfrentei os erros acima e lutei bastante para descobrir a causa raiz. Sugiro tentar adicionar o argumento da JVM "-XX: -UseSplitVerifier" durante a execução do aplicativo.


1

Após a atualização Gradleno Android Studio 3.6.1, ocorreram falhas na API 19 na compilação da versão.

Ocorreu um erro naGlide biblioteca . A solução é reescrever proguard-rules.txt .

Também desclassificar o Gradleworks ( classpath 'com.android.tools.build:gradle:3.5.3'), mas é uma solução desatualizada, não a use.


0

Embora o motivo mencionado por Kevin esteja correto, mas eu definitivamente verificaria abaixo antes de passar para outra coisa:

  1. Verifique cglibsno meu caminho de classe.
  2. Verifique as hibernateversões no meu caminho de classe.

É provável que uma versão múltipla ou conflitante de qualquer uma das opções acima possa causar problemas inesperados, como o que está em questão.


0

java.lang.VerifyError significa que o código de código compilado está se referindo a algo que o Android não consegue encontrar. Este confirmError emite-me apenas com kitkat4.4 e versão inferior que não está na versão acima, mesmo que eu executei a mesma compilação nos dois dispositivos. quando usei o analisador jackson json da versão anterior, ele mostra java.lang.verifyerror

compile 'com.fasterxml.jackson.core:jackson-databind:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-core:2.2.+'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.2.+'

Então eu mudei a Dependency para a versão mais recente 2.2 para 2.7 sem a biblioteca principal , e então ela funciona. o que significa que os métodos e outros conteúdos do núcleo são migrados para a versão mais recente do Databind2.7 . Isso corrige meus problemas.

compile 'com.fasterxml.jackson.core:jackson-annotations:2.7.0-rc3'
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.0-rc3'

Como você sabe qual JAR procurar?
Siddharth

1
jackson-core: 2.2. + tornou-se legado. portanto, precisamos usar databind: 2.7.0-rc3, anotações: 2.7.0-rc3 ou versão mais recente que esta. Este 2 é suficiente, evite o jackson-core: 2.2. +. Eu recebi algum erro de verificação naquele momento. enquanto estiver usando a versão 2.7+, ele não mostra esse erro
Anand Krish

0

remova qualquer arquivo jar inutilizável e tente executar. e seu trabalho para mim, eu adicionei um arquivo jar jcommons e também outro arquivo jar jcommons.1.0.14, para remover o jcommons e seu trabalho para mim


0

escreva no arquivo:

{Wildfly-home}\modules\system\layers\base\org\picketbox\main 

em dependências a seguir: <module name="sun.jdk"/>


-1

No meu caso, eu estava recebendo um erro de verificação com o rastreamento de pilha abaixo

jasperreports-server-cp-6.4.0-bin\buildomatic\build.xml:61: The following error occurred while executing this line:
TIB_js-jrs-cp_6.4.0_bin\jasperreports-server-cp-6.4.0-bin\buildomatic\bin\setup.xml:320: java.lang.VerifyError: (class: org/apache/commons/codec/binary/Base64OutputStream, method: <init> signature: (Ljava/io/OutputStream;ZI[B)V) Incompatible argument to function
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.createKeystore(KeystoreManager.java:257)
    at com.jaspersoft.jasperserver.crypto.KeystoreManager.init(KeystoreManager.java:224)
    at com.jaspersoft.buildomatic.crypto.KeystoreTask.execute(KeystoreTask.java:64)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.taskdefs.Sequential.execute(Sequential.java:68)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:169)
    at org.apache.tools.ant.taskdefs.ImportTask.importResource(ImportTask.java:222)
    at org.apache.tools.ant.taskdefs.ImportTask.execute(ImportTask.java:163)
    at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
    at org.apache.tools.ant.Task.perform(Task.java:348)
    at org.apache.tools.ant.Target.execute(Target.java:435)
    at org.apache.tools.ant.helper.ProjectHelper2.parse(ProjectHelper2.java:180)
    at org.apache.tools.ant.ProjectHelper.configureProject(ProjectHelper.java:93)
    at org.apache.tools.ant.Main.runBuild(Main.java:826)
    at org.apache.tools.ant.Main.startAnt(Main.java:235)
    at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
    at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Eu o resolvi removendo a entrada do caminho de classe para commons-codec-1.3.jar; havia uma incompatibilidade na versão deste jar com a que acompanha o Jasper.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.