Existem funções embutidas em java?

112

Existe um conceito de funções inline em java ou substituiu alguma outra coisa? Se houver, como é usado? Já ouvi isso public, statice os finalmétodos são funções embutidas. Podemos criar nossa própria função embutida?

giri
fonte
4
Só para esclarecer, você quer dizer en.wikipedia.org/wiki/Inline_function , não en.wikipedia.org/wiki/Anonymous_function , certo?
JW.
3
Como um pequeno comentário, a otimização prematura é a raiz de todos os males. Sem compreender totalmente a natureza de público, estático e final, você não pode realmente entender o impacto que o inlining pode ter - e isso depende da JVM que você está usando. Certifique-se de responder primeiro por que você precisa incorporar algo: é quase certo que existem otimizações de ROI mais altas que você pode fazer em outro lugar.
Nathaniel Ford de
1
Consulte também stackoverflow.com/q/7772864/632951
Pacerier

Respostas:

123

Em Java, as otimizações geralmente são feitas no nível da JVM. No tempo de execução, a JVM executa algumas análises "complicadas" para determinar quais métodos embutir. Ele pode ser agressivo no in-line, e o Hotspot JVM pode, na verdade, métodos inline não finais.

Os compiladores java quase nunca embutem nenhuma chamada de método (a JVM faz tudo isso em tempo de execução). Eles fazem constantes de tempo de compilação em linha (por exemplo, valores primitivos estáticos finais). Mas não métodos.

Para mais recursos:

  1. Artigo: O Java HotSpot Performance Engine: Método Inlining Exemplo

  2. Wiki: Inlining no OpenJDK , não totalmente preenchido, mas contém links para discussões úteis.

notnoop
fonte
15

Não, não há função embutida em java. Sim, você pode usar um método estático público em qualquer lugar do código quando colocado em uma classe pública. O compilador java pode fazer expansão sequencial em um método estático ou final, mas isso não é garantido.

Normalmente, essas otimizações de código são feitas pelo compilador em combinação com o JVM / JIT / HotSpot para segmentos de código usados ​​com frequência. Além disso, outros conceitos de otimização, como declaração de registro de parâmetros, não são conhecidos em java.

Otimizações não podem ser forçadas por declaração em java, mas feitas por compilador e JIT. Em muitas outras linguagens, essas declarações são freqüentemente apenas dicas do compilador (você pode declarar mais parâmetros de registro do que o processador, o resto é ignorado).

Declarar métodos java como static, final ou private também são dicas para o compilador. Você deve usá-lo, mas sem garantias. O desempenho do Java é dinâmico, não estático. A primeira chamada para um sistema é sempre lenta devido ao carregamento da classe. As próximas chamadas são mais rápidas, mas dependendo da memória e do tempo de execução, as chamadas mais comuns são otimizadas dentro do sistema em execução, de modo que um servidor pode se tornar mais rápido durante o tempo de execução!

Arne Burmeister
fonte
3
finalnão causa impacto no JIT inlining
Steve Kuo
1
+1, mas como podemos testar se a versão compilada de um método está embutida?
Pacerier de
@Pacerier Mas por que devemos testar se algo está embutido?
Arne Burmeister
14

Java não fornece uma maneira de sugerir manualmente que um método deve ser embutido. Como @notnoop diz nos comentários, o inlining é normalmente feito pela JVM em tempo de execução.

Thomas Owens
fonte
3
A maioria dos compiladores java nunca chama métodos sequenciais. Quase sempre a JVM faz isso.
notnoop
Obrigado por esclarecer isso. Eu não tinha certeza de em que fase isso aconteceu, exatamente. Vou editar minha postagem para refletir isso.
Thomas Owens
@ThomasOwens sim, mas não é públicojdk.internal.vm.annotation.ForceInline
Eugene
4

O que você disse acima está correto. Às vezes, os métodos finais são criados como sequenciais, mas não há outra maneira de criar explicitamente uma função sequencial em java.

GreenieMeanie
fonte
5
Os métodos finais não são garantidos como sequenciais.
Thomas Owens
4
No HotSpot, adicionar finalnão faz nenhuma diferença se o método é embutido ou não.
Tom Hawtin - tackline
4
@Thomas - é por isso que eu disse "Às vezes métodos finais ..."
GreenieMeanie
@ TomHawtin-tackline, você tem uma fonte confiável para isso? Até onde eu sei, os métodos finais podem ser sequenciados sem empregar um protetor de tipo, o que significa que o modificador torna o método sequencial mais eficiente do que sem o modificador. Eu sei que a Jikes RVM leva isso em consideração ao decidir se deseja embutir. Tem certeza de que o HotSpot não faz algo semelhante?
Jannik Jochem
2

Exemplo da vida real:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

Então, em outras aulas, posso sair se o código tiver expirado. Se eu fizer referência à variável EXPIRED_ON de outra classe, a constante é embutida no código de byte, tornando muito difícil rastrear todos os lugares no código que verifica a data de validade. No entanto, se as outras classes invocarem o método isExpired (), o método real é chamado, o que significa que um hacker pode substituir o método isExpired por outro que sempre retorna falso.

Concordo que seria muito bom forçar um compilador a embutir o método final estático em todas as classes que fazem referência a ele. Nesse caso, você não precisa nem incluir a classe Control, pois ela não seria necessária em tempo de execução.

Pela minha pesquisa, isso não pode ser feito. Talvez algumas ferramentas do Obfuscator possam fazer isso, ou você pode modificar seu processo de construção para editar as fontes antes de compilar.

Para provar se o método da classe de controle é colocado embutido em outra classe durante a compilação, tente executar a outra classe sem a classe Control no caminho de classe.

Billy Guthrie
fonte
2

Bem, existem métodos que podem ser chamados de métodos "inline" em java, mas dependendo do jvm. Após a compilação, se o código de máquina do método for menor que 35 bytes, ele será transferido para um método embutido imediatamente; se o código de máquina do método for menor que 325 bytes, ele pode ser transferido para um método embutido, dependendo do jvm.

Ethan
fonte
1
Esses são os valores padrão para VM da Oracle, consulte docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller
0

então, parece que não existe, mas você pode usar esta solução alternativa usando goiaba ou uma implementação de classe de função equivalente, porque essa classe é extremamente simples, por exemplo:

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

sim, este é um código morto apenas para exemplificar como criar um bloco de código complexo (dentro de {}) para fazer algo tão específico que não deve nos incomodar em criar qualquer método para isso, também conhecido como inline!

Aquarius Power
fonte
Parece uma ideia razoável. Você tem uma versão disso que não usa as bibliotecas comuns do Google?
ragerdl
0

Java9 tem um compilador "adiantado" que faz várias otimizações em tempo de compilação, em vez de tempo de execução, o que pode ser visto como embutido.

tkruse
fonte