Constante muda na descompilação

Bom dia a todos!
Precisei descompilar algumas classes e notei que (aparentemente acontece isso) os valores das constantes é que foram geradas no código ao invés da variável em si.
exemplo:Tenho a constante “ixxx=1;”
ao descompilar onde deveria estar a variável “xxx”, o decompilador gerou o valor “1”.

Há alguma outra coisa maluca em que possa acontecer na decompilação? É normal acontecer isso?

obrigado

Se a constante for de tipo primitivo (private static final int), então ela normalmente será substituída, pelo compilador, pelo seu valor. (Isso não costuma ocorrer no caso de constantes de tipo objeto, como Strings, mas não há nada que proíba o compilador de usar o valor e não a constante em si).

Isso é esperado, porque foi o próprio compilador que faz isso (não é o descompilador que fez isso).

E é isso que quebra as pernas de um monte de gente boa mas ingênua - acham que constantes são coisas que podem ser mudadas, como arquivos de configuração, e tentam trocar uma classe (arquivo .class) mudando só essas constantes. O problema é que o valor das constantes é que foi usado na compilação, então se você só mudar o .class, sem recompilar seu programa, pode acabar usando valores antigos.

A descompilação pode ter problemas com:

a) Blocos try/catch - os descompiladores costumam se confundir com esses blocos;
b) Generics - a informação de generics é quase toda perdida na compilação, exceto em alguns pontos;
c) Algumas estruturas de controle um pouco mais complicadas.
d) Código “sintético” - por exemplo, classes internas anônimas costumam gerar bastante código sintético para acessar variáveis privadas das classes mais externas.

Portanto, eu aconselho a você aprender um pouco sobre bytecodes e o “javap”.
Pode ser que você tenha alguns métodos que devam ser descompilados “manualmente” já que o descompilador se perdeu.

Sim, é normal. E isso se chama inlining.

É uma das técnicas mais comuns de otimizações do compilador.
Outras podem ser encontradas aqui: http://en.wikipedia.org/wiki/Compiler_optimization

Funções também podem ser tornadas inline. O compilador pode substituir um código assim:

[code]public static void main(String[] args) {
double a = 10.0;
double b = 9.5;
double c = soma(a, b);
}

public static double soma(double a, double b) {
return a+b;
}
[/code]

Por um assim:

public static void main(String[] args) { double c = a+b; }

Veja o artigo que tem uma lista bem grande e explicativa das otimizações mais comuns.

O “inlining” em Java normalmente é feito pela JVM, não pelo javac.
Tanto é que setters e getters são otimizados (via inlining) quando a JVM roda em modo server, ou então usando a opção -XX:+UseFastAccessorMethods.
É que uma das coisas que a JVM faz é sempre imprimir o stack trace mais preciso possível, mesmo que ele não corresponda exatamente ao código efetivamente rodado. Nesse caso, a JVM simula que executou o código não - otimizado, mas nesse caso o código (bytecodes gerados pelo javac) também não pode estar otimizado.

Só para exemplificar, digamos que você tivesse o seguinte setter:

public void setInterval (int x) {
    this.interval = 100000 / x;
}

Este setter pode ser otimizado usando inlining, mas nem por isso pode deixar de gerar uma exceção (divisão por zero). Se ele gerar uma exceção, então o stack trace deve incluir uma referência ao método setInterval, mesmo que esse método não exista de verdade no código de máquina que foi gerado.

Portanto, uma das pouquíssimas otimizações que o javac faz é só essa de pegar o valor de uma constante, e usá-lo diretamente, em vez de pegá-lo de um campo ou variável.

Show, obrigado pessoal.
Na verdade não vou usar o código, precisei fazer este trabalho reverso apenas para comparar o que foi feito em duas versões mais atuais de entrega para o cliente.
Tenho o fonte apenas da antepenúltima entrega, entende!!

Outro coisa que parece ter acontecido é que a declaração de variáves “mudaram de escopo”. Tipo, “sairam” de dentro de um while e passaram para o início do método.

Com certeza vou me informar melhor.Valeu mesmo.
Acredito que o post ajudará outras pessoas.

[]

Isso no caso da VM da Sun. A própria descrição do método getStackTrace() da interface throwable prevê que outras VMs ou compiladores possam fazer inlining mais agressivo.