BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias Byte Buddy fornece suporte completo ao Java 11

Byte Buddy fornece suporte completo ao Java 11

A nova versão do Byte Buddy, biblioteca muito utilizada para engenharia de bytecodes Java, fornece suporte completo ao Java 11 e todos os novos recursos de classfile e bytecode introduzidos desde o Java 8. Isso inclui o novo recurso ConstantDynamic (também chamado de condy) e o Nestmates do Java 11.

O InfoQ conversou com Rafael Winterhalter, autor do ByteBuddy, sobre essa nova versão.

InfoQ: Obrigado por conversar conosco. Por favor, explique o que é o Byte Buddy? Quais suas funcionalidades? Para que tipo de aplicativos é usado? Há quanto tempo existe esse projeto? Como os desenvolvedores podem começar a usá-lo?

Rafael Winterhalter: O Byte Buddy é uma biblioteca de geração de código que permite definir novas classes ou modificar classes existentes usando uma simples API Java. Para isso, a biblioteca gera e manipula o bytecode Java. Ao trabalhar no nível de bytecodes, é possível interagir com o código que é gravado em qualquer linguagem que executa na JVM e a biblioteca pode ser usada durante em tempo de execução do aplicativo Java para modificar o código que está sendo executado atualmente, incluindo seu próprio código.

O Byte Buddy é usado principalmente por outras bibliotecas e frameworks. Por exemplo, o Hibernate usa o Byte Buddy para implementar proxies de entidades e o Mockito usa para gerar classes simuladas. Cada vez mais, o Byte Buddy também é usado para desenvolver agentes Java que alteram o comportamento de aplicativos inteiros. Usando esses agentes, as ferramentas de APM, como o Instana, estão usando o Byte Buddy para coletar métricas de aplicativos durante o tempo de execução.

Comecei a trabalhar no Byte Buddy em 2014 e lançamos a primeira versão não beta em 2015. Desde então, ele ganhou muita aceitação e uso. Hoje em dia, a biblioteca é baixada quase cem milhões de vezes por ano.

Para começar, basta adicionar a biblioteca no projeto e gerar uma classe usando sua DSL. A página do GitHub e a página inicial do Byte Buddy mostram um exemplo simples de como criar uma classe simples. Para ampliar esse exemplo, há uma documentação abrangente na página da Web e muito material em diferentes blogs, no YouTube e no Vimeo.

InfoQ: Vamos conversar sobre a nova versão. O que foi adicionado recentemente? Quais são os novos recursos que os usuários solicitaram?

Winterhalter: Nos últimos lançamentos trabalhei com suporte ao Java 11 e 12. Mas a maior parte do tempo foi para adicionar suporte ao sistema de módulos do Java, o que era um longo caminho a percorrer. Mas com os últimos lançamentos, o suporte para o sistema de módulos se tornou estável e o Byte Buddy irá adicionar um module-info.class em sua versão 1.9.0. Ao mesmo tempo, a biblioteca mantém a compatibilidade com o Java 6, 7 e 8, nas quais essa classe é ignorada.

As solicitações de recursos geralmente incluem suporte das versões mais recentes do Java, pois a falta de suporte geralmente impede que os projetos sejam construídos em VMs mais recentes. Da mesma forma, muitas solicitações de recursos envolvem suporte a linguagens que executam na JVM, como Kotlin ou Scala, que possuem algumas particularidades quando se trata de sua tradução para bytecode. Ao adicionar um novo recurso no Java, isso é feito de maneira muito conservadora e pode ser necessário ampliar os recursos da JVM. Algumas linguagens tentam emular um comportamento específico, fazendo com o Byte Buddy falhar em alguma tarefa.

InfoQ: Passando para o novo ciclo de lançamento, como fabricante de ferramentas, como foi o impacto causado pelo ritmo mais rápido e pelas alterações no formato do arquivo da classe Java?

Winterhalter: Para cada versão do Java, o Byte Buddy precisa ser ajustado para as mudanças no formato do arquivo da classe Java. Muitas vezes, as mudanças são triviais, mas também podem ser bastante complexas. Por exemplo, quando o Java 8 foi lançado, o Byte Buddy teve que se adaptar ao conceito de código nas interfaces por meio de métodos default. Isso soa como uma pequena alteração, mas exigiu muita refatoração, pois a suposição de que os métodos foram definidos na hierarquia de classes foi tomada como garantida em vários locais dentro da implementação. Com o ritmo mais acelerado dos lançamentos do Java, o trabalho infelizmente se tornou um pouco mais cansativo, mas no final do dia não reclamo dos novos recursos sendo adicionados à plataforma que está no centro da minha vida profissional.

Um problema que enfrento por estar na parte de baixo da pilha é que muitas bibliotecas dependem do Byte Buddy, de modo que recebo suporte rapidamente após cada nova versão do Java. Sem essas atualizações, as bibliotecas que dependem do Byte Buddy não podem suportar uma nova versão do Java, o que impede a adoção de outros mantenedores. Ao mesmo tempo, muitas ferramentas como o Maven também precisam de algum tempo para suportar uma nova versão do Java, o que também dificulta a movimentação rápida. E uma versão nova a cada meio ano é bem rápido. No entanto, sinto que outros fornecedores de ferramentas já estão adotando as mudanças. O suporte ao Java 10 para o Java 12 foi mais fácil em comparação com as versões anteriores, também porque menos alterações são agrupadas em uma única atualização.

InfoQ: O Java 11 traz o ConstantDynamic como um novo recurso. Qual é o significado disso? Como funciona? Está relacionado com InvokeDynamic? Se sim, como?

Winterhalter: Os desenvolvedores Java normalmente definem suas constantes armazenando um valor em um campo final e estático. No entanto, o formato do arquivo da classe Java permite constantes que não são armazenadas em campos, mas que são referenciadas por algum símbolo. Vários tipos já expressam tais símbolos como literais; as Strings são expressas como literais, por exemplo, são vinculadas a esses símbolos no conjunto constante do arquivo de classe.

Com o ConstantDynamic, é possível expressar qualquer instante como um valor constante referenciado no pool de constantes. A utilização das constantes no arquivo de classe tem a grande vantagem de o valor constante precisar ser criado apenas quando for usado pela primeira vez e não quando a classe for carregada, como é o caso dos campos finais estáticos. Usando o ConstantDynamic, muito carregamento que é feito na inicialização da JVM poderia ser evitado e carregado apenas quando for necessário. Por exemplo, em qualquer inicialização da JVM, ela deve inicializar a classe Locale que se refere a todos os idiomas que a JVM suporta. Essa inicialização é bastante cara e muitas vezes desnecessária, já que a maioria dos programas usa apenas o idioma padrão. Usando o ConstantDynamic, as bibliotecas centrais poderiam ser melhoradas no futuro para permitir uma inicialização mais rápida da JVM e, claro, outras bibliotecas poderiam fazer coisas semelhantes.

A partir de hoje, o ConstantDynamic não é exposto pela linguagem Java ou por qualquer outra linguagem da JVM. Mas, como seu suporte a JVM é totalmente funcional, o Byte Buddy é capaz de criar constantes dinâmicas no bytecode. As constantes dinâmicas são criadas pela implementação de um método de inicialização que retorna o valor da constante como resultado. Este método de inicialização é então referenciado no local onde o valor constante deve ser usado.

Fiz um post explicando em detalhes o ConstantDynamic e InvokeDynamic, e como fazer uso de ambos com o Byte Buddy. O InvokeDynamic é muito semelhante, a diferença é que usa um método de inicialização para vincular uma chamada e não um valor constante. E, claro, o Byte Buddy também oferece uma API para ele.

InfoQ: Houve alguma outra mudança significativa no formato do arquivo da classe desde o Java 8? Como o ByteBuddy respondeu às mudanças?

Winterhalter: Além do ConstantDynamic, a JVM adicionou o conceito de nest mates para fornecer um controle de acesso aos método das classes aninhadas. Ao definir duas classes como nest mates em seus respectivos arquivos de classe, eles ganham o privilégio de invocar os métodos privados uns dos outros. Anteriormente, as classes aninhadas só podiam invocar os métodos privados uns dos outros, porque o compilador javac adicionava métodos de acesso privado aos pacotes para qualquer chamada desse tipo. Isso obviamente abre a classe além do escopo pretendido, e é por isso que um mecanismo explícito é preferível e também mais fácil de entender.

O Byte Buddy suporta nestmates existentes, mas atualmente seu DSL não pode alterar ou adicionar posicionamentos de nest. Esta será uma característica maior que pretendo implementar até o final do ano.

InfoQ: E o futuro? Qual é a sua opinião sobre os recursos futuros que estão atualmente no roadmap?

Winterhalter: No momento, quase todos os novos recursos do Java me entusiasmam. O recurso que mais antecipei é o projeto Loom, que inclui suporte nativo para futuras versões da JVM. No trabalho como consultor de software, regularmente encontro projetos que tentam a simultaneidade usando abstrações como um modelo de ator ou callbacks reativos. Normalmente, esses aplicativos crescem em complexidade ao longo do tempo, e a lógica de negócios fica oculta no código cerimonial que modela a simultaneidade. Isso às vezes torna difícil refatorar o código comercial, já que ele é distribuído de maneiras que seguem as demandas técnicas, em vez da lógica do domínio. Espero que o Loom torne desnecessário modelar explicitamente a simultaneidade em todo o código comercial na maioria dos casos.

Além do Loom, estou ansioso para ampliar o suporte ao compilador Graal, que é um importante marco para a JVM mantendo seu lugar como um dos melhores tempos de execução do mundo. Além da compilação JIT, os recursos para compilação AOT e criação de imagens nativas estenderão o escopo no qual o Java será usado no futuro. Também espero que o projeto Metropolis ajude a preencher algumas lacunas entre o conhecimento da maioria dos desenvolvedores Java e o funcionamento da JVM.

InfoQ: Algum outro comentário que gostaria de compartilhar com os leitores?

Winterhalter: Muitas vezes sinto que uma parte dos desenvolvedores Java é cética em relação à administração da Oracle, e muitas vezes acham que recursos como o sistema de módulos ou o novo ciclo de lançamento implicam em mais trabalho do que benefícios.

Em contraste, acho que a Oracle finalmente cuidou de muitos problemas que teriam comprometido o futuro a longo prazo da plataforma. A JVM está melhor do que nunca e muitas mudanças que virão são baseadas nessa base. É um momento emocionante para ser um desenvolvedor Java e todos temos muito o que esperar.

Para os desenvolvedores interessados, há vários vídeos que estão disponíveis com mais informações.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT