
-
Explore a interoperabilidade entre Swift e Java
Saiba como você pode usar o Swift e o Java juntos em uma única base de código. Vamos apresentar o projeto de interoperabilidade Swift-Java, que permite usar o Swift em programas do Java ou vice-versa. Mostraremos como usar as ferramentas e bibliotecas oferecidas pelo Swift-Java para escrever código seguro, eficiente e totalmente integrado entre as duas linguagens.
Capítulos
- 0:00 - Introdução
- 2:41 - Diferenças nos tempos de execução
- 3:31 - Métodos nativos do Java
- 6:29 - Swift-Java
- 10:13 - Chamar o Java no Swift
- 14:01 - Chamar o Swift no Java
- 20:47 - Conclusão
Recursos
Vídeos relacionados
WWDC25
- Combine C, C++ e Swift com segurança
- Melhore o uso da memória e o desempenho com o Swift
- Novidades do Swift
WWDC23
-
Buscar neste vídeo...
Olá! Meu nome é Konrad. Sou engineer na equipe Swift Language. Gostaria de apresentar um novo esforço de interoperabilidade que começamos no início deste ano: interoperabilidade Swift-Java. Estamos animados com a interoperabilidade, pois amplia a gama de apps em que podemos usar o Swift. Com ela, podemos introduzir aos poucos o Swift em bases de código escritas em outras linguagens. Não precisamos fazer reescritas grandes e arriscadas, podemos só adicionar um novo recurso ou substituir um atual pelo Swift sem tocar no resto da base de código. Podemos reutilizar bibliotecas implementadas em outras linguagens. Podemos disponibilizar bibliotecas escritas em Swift para elas. O jeito como abordamos a interoperabilidade vai além da linguagem, pois nos integramos às ferramentas de criação mais apropriadas para cada ecossistema, como CMake para C ou C++ ou Gradle para projetos Java. A interoperabilidade com linguagens C é um recurso de ponta do Swift desde o início. Ela permitiu que o Swift se integrasse ao ecossistema de desenvolvedores Apple e se tornasse a linguagem principal para desenvolvimento nessas plataformas. Há dois anos, iniciamos o esforço de interoperabilidade com C++, que permitiu a combinação de bibliotecas C++ e Swift em uma base de código. Isso abriu muitas possibilidades para o uso do Swift em mais lugares. Para saber mais, confira as sessões “Combinação de Swift e C++”, da WWDC 2023, ou “Combinação segura de C, C++ e Swift”, deste ano. Quando falamos de interoperabilidade, podemos focar em duas direções. Ao escrever um app principalmente em Swift, podemos chamar um código escrito em Java. Ou podemos tornar o Swift fácil e eficiente para ser chamado no Java. A interoperabilidade com Java do Swift permite as duas direções. As ferramentas e técnicas que usamos em cada direção são diferentes, mas pode ser que você use todas elas em um só projeto. Antes dos exemplos específicos, vamos revisar as diferenças entre os tempos de execução do Java e do Swift. Depois, veremos três exemplos de uso da interoperabilidade com Java. Usaremos o recurso de métodos nativos existente do Java. Exploraremos como tornar uma biblioteca Java inteira acessível ao Swift. E exploraremos a direção oposta e encapsularemos uma biblioteca Swift inteira para fácil consumo por um projeto Java. Vamos começar comparando os tempos de execução. O tempo de execução do Java é diferente das linguagens nativas com as quais o Swift tem interoperabilidade. Sob uma perspectiva mais ampla, podemos dizer que o Swift é a linguagem nativa mais semelhante ao Java. Ambas oferecem classes com um modelo de herança semelhante, fornecem gerenciamento automático de memória, bastante transparente para quem desenvolve, e oferecem um sistema genérico semelhante, embora representado de forma diferente no tempo de execução. Por fim, erros do Swift podem ser gerados, assim como exceções Java. Mas a quantidade de informações carregada no tempo de execução é um pouco diferente. O importante é que, ao escolher cuidadosamente como interagir com esses recursos, podemos expressar a maioria das APIs de uma linguagem na outra. Agora que nos lembramos das diferenças e semelhanças dessas linguagens, vamos começar e ver como podemos estender um app Java existente. Vamos começar com algo simples e focar na implementação de uma só função no Swift. Para isso, usaremos o recurso da linguagem Java chamado Métodos Nativos. Os Métodos Nativos do Java fazem parte da API Java Native Interface (JNI). A JNI é parte do Java desde 1997, ou seja, antes do iPod, e foi projetada para o Java interoperar com código nativo. Ela é utilizada para atingir metas de desempenho, movendo trabalho do heap Java, ou usar bibliotecas nativas que não têm um equivalente Java. Ainda é um dos principais modos pelos quais o Java e o código nativo interoperam, e as APIs não mudaram desde então. Portanto, faz sentido começarmos a nossa exploração com a JNI. Para conhecer a JNI, vamos seguir as etapas tradicionais que teríamos que seguir para usá-la sem bibliotecas ou ferramentas de suporte. No app Java, você definiria uma função nativa, que será implementada usando código nativo. Para ilustrar como a JNI lida com a passagem de objetos para código nativo, usamos os tipos Uppercase Integer como argumentos e tipo de retorno dessa função. Diferentemente de valores Int primitivos, são objetos Java e teremos que trabalhar com eles de acordo. Você teria que usar o compilador Java com um sinalizador “-h” nos arquivos que contêm métodos nativos. Isso resultará em um arquivo de cabeçalho C com declarações de função C que a JVM tentará invocar quando o método nativo Java correspondente for chamado. A declaração tem um nome detalhado: Java_com_example_JNIExample_compute, que corresponde ao nome do pacote, do método e da classe do método nativo. Ela aceita o ambiente JNI, o parâmetro jobject desta referência do objeto Java em que estamos chamando o método e todos os parâmetros da declaração de função Java original. Por fim, você implementaria essa função na linguagem nativa de sua escolha, que para nós seria o Swift.
É muito código, não é? Embora o texto padrão esteja abafando o ruído para a implementação lógica, que está aqui, não é só ruído. São inúmeras oportunidades de errar, o que resultaria em uma falha. Em suma, a JNI é um jeito compatível de chamar código nativo da JVM, mas é difícil de usar corretamente. Para tornar as implementações de método eficazes, talvez precisemos envolver cache e outras técnicas que complicam ainda mais o código. Há etapas de criação e cabeçalhos C adicionais para se preocupar. A correspondência manual de assinaturas de método e strings mágicas é propensa a erros. Temos que gerenciar com cuidado o ciclo de vida de todos os objetos Java criados ou recebidos. Portanto, usar a JNI sem suporte adicional é possível, mas não é uma ótima experiência. O que nos leva ao SwiftJava, o novo lar do esforço de interoperabilidade entre Swift e Java. O objetivo do SwiftJava é fornecer a desenvolvedores de Swift e Java uma forma flexível, segura e eficiente de interagir entre as duas linguagens.
O SwiftJava consiste em peças usadas de forma independente ou em conjunto. Um pacote Swift, que fornece a biblioteca e a macros JavaKit, que aumentam a segurança do processamento de código da JNI, como mostramos no exemplo anterior. Uma biblioteca Java chamada SwiftKit. Ela ajuda os apps em Java a lidar com objetos em Swift. A ferramenta de linha de comando Swift-Java e integrações com sistemas de criação, como o plug-in SwiftPM, ou formas de trabalho em andamento de integração com ferramentas de criação em Java populares, como o Gradle. Vamos repetir o último exemplo usando as ferramentas fornecidas pelo SwiftJava. Em vez de um compilador Java, usaremos a linha de comando Swift-Java para gerar a ponte necessária. Precisamos fornecer um nome de módulo onde as fontes geradas devem ser gravadas e configuração adicional. Em projetos complexos, isso seria acionado por um plug-in de criação em SwiftPM ou um sistema de criação que você esteja usando. O resultado é um arquivo Swift com decorações que descrevem a classe Java importada. Se o tipo Java tivesse algum método de membro, ele apareceria no tipo Swift correspondente, permitindo que chamássemos essas funções Java no Swift. Por fim, o protocolo JNIExampleNativeMethods gerado contém todos os métodos nativos que podemos implementar para esse tipo. Isso serve como substituição para o cabeçalho C que estávamos usando. Para implementar sua função de computação nativa, basta escrever uma extensão na classe JNIExample gerada e adequá-la ao protocolo JNIExampleNativeMethods. Também temos que anotá-la usando a macro JavaImplementation que é fornecida pelo JavaKit. Depois, o compilador nos ajudará a implementar a assinatura de função necessária correta. Lembre-se também que precisamos fazer anotações com a macro JavaMethod, que lida com mais alguns detalhes da JNI para nós. Graças ao SwiftJava, a implementação de método ficou mais simples e podemos focar apenas na lógica de negócios. Melhor ainda, como estamos no Swift, podemos usar qualquer biblioteca Swift que quisermos. Por exemplo, posso usar uma implementação nativa de algum algoritmo criptográfico. O ecossistema do Swift tem uma ótima biblioteca para isso. Posso importar o módulo de criptografia e, por exemplo, calcular o hash SHA256 dos dados passados. Talvez você se lembre da lista de problemas que tivemos na implementação da JNI. A maioria deles não envolve tanto a JNI, e sim como foi difícil usá-la corretamente. Graças à abordagem do SwiftJava à JNI, podemos evitar muito código repetitivo, e o código resultante é muito mais fácil de manter e salvar por padrão. Não precisamos interagir com cabeçalhos C e podemos confiar em assinaturas de função geradas e bem-tipadas. Isso evita erros, que podem levar muito tempo para depurar. Por fim, o gerenciamento do ciclo de vida do objeto é muito melhor em comparação com a escrita manual da cola entre as linguagens. Isso é crucial no código seguro para memória que ultrapassa barreiras de linguagem. No geral, é muito mais agradável e seguro fazer interações JNI com o SwiftJava em vez de escrevê-las à mão. Estamos apenas começando, e o SwiftJava tem muito mais a oferecer. Vamos considerar que gostaríamos de usar uma biblioteca Java no Swift. Usaremos a ferramenta Swift-Java, mas vamos focar em como abordaríamos a importação de uma biblioteca Java inteira, não de um único tipo. Digamos que eu queira usar a popular biblioteca Java Apache Commons CSV no Swift. Preciso encontrar a biblioteca em si e todas as suas dependências downstream. A resolução de dependências complica rapidamente, pois as bibliotecas Java têm muitas dependências transitivas, que têm as próprias dependências e por aí vai. Felizmente, o SwiftJava pode cuidar disso para nós. Basta preparar as coordenadas de artefatos da biblioteca que gostaríamos de usar. Você pode encontrá-las facilmente pesquisando online ou pode perguntar a um profissional desenvolvedor Java em sua equipe. A dependência será expressa como uma tríplice: ID de artefato identificando o artefato, ID de grupo identificando a organização que publica a biblioteca e um número de versão. Usaremos a integração com o Gradle do SwiftJava, uma ferramenta de criação e um gerenciador de dependências no ecossistema do Java. Para expressar essa dependência ao Gradle, basta colocar colunas entre esses três valores. Assim, formamos um descritor de dependência em um formato que o Gradle entende. Agora que sabemos as coordenadas de dependências, temos duas opções para baixá-las e encapsulá-las em nosso destino JavaApacheCommonsCSV. A primeira é usar o plug-in da ferramenta de criação SwiftJava. No arquivo swift-java.config de destino, adicionaríamos uma seção relacionando as dependências raiz a serem resolvidas. Isso é muito bom. O plug-in invocará automaticamente o Gradle para resolver dependências do Java sempre que criarmos nosso projeto do SwiftPM. Mas o SwiftPM impõe um sandbox de segurança que impede o acesso de plug-ins criados a arquivos arbitrários e à rede. Portanto, se você quiser usar essa abordagem, poderá desativar o sandbox de segurança ao criar o projeto. Isso pode não ser viável em todos os ambientes. Você pode adotar esta abordagem alternativa. Podemos usar o comando Resolve da ferramenta de linha de comando Swift-Java. Fornecendo um nome de módulo com o arquivo config, ela resolverá as dependências e gravará o caminho de classe resultante em um arquivo. Como isso é realizado fora da criação do SwiftPM, não é necessário desativar o sandbox. Isso significa que você teria que acionar manualmente a resolução de dependências antes de criar seu projeto. É uma troca, e você pode escolher o modelo ideal para seu fluxo de trabalho.
De qualquer forma, podemos usar a biblioteca Java no Swift. Basta importar os módulos JavaKit e JavaApacheCommonsCSV. Depois, iniciamos a JVM no nosso processo Swift para executar o código Java. Assim, podemos usar Java no nosso app do Swift. Estamos usando o FileReader do JDK e passando-o para a biblioteca CSV que acabamos de importar. Podemos usar os loops for-each do Swift diretamente nas coleções Java retornadas.
Vimos como o SwiftJava usa o Gradle e o SwiftPM para proporcionar uma ótima experiência ao usuário. Podemos importar bibliotecas Java inteiras sem ter que modificar fontes do Java. O código do Swift gerado pela fonte usa tipos de wrapper JDK fornecidos pelo JavaKit e lida bem com tipos definidos pelo usuário. O JavaKit simplifica o gerenciamento do ciclo de vida de objetos Java, promovendo referências a esses objetos a referências globais, quando necessário. A última técnica que discutiremos é disponibilizar uma biblioteca Swift inteira para um app do Java. É um caso de uso importante porque permite implementar uma lógica de negócios básica crucial em Swift e usá-la em apps e serviços, independentemente de já terem adotado o Swift ou não.
Já mencionamos que a interoperabilidade deve ser bidirecional. Vale a pena internalizar que, ao tornar a direção de Java para Swift uma ótima experiência, podemos usar o Swift em mais projetos e nos divertir, algo importante na introdução de uma nova linguagem em uma base de código. Se fôssemos abordar a exposição de uma biblioteca Swift inteira usando as técnicas anteriores, teríamos que escrever muitas funções de wrapper no Java. Para algumas funções, tudo bem, mas para uma biblioteca inteira, é hora de considerar uma abordagem diferente. Assim como fizemos para expor uma biblioteca Java ao Swift, agora vamos tornar a chamada ao Swift o mais fácil possível para o Java. Encapsularemos os tipos da biblioteca Swift com classes Java e os distribuiremos juntos como uma biblioteca Java. Desta vez, não usaremos a JNI. Usaremos a nova API Foreign Function and Memory que foi estabilizada em março do ano passado e está disponível desde o Java 22. Ela oferece melhor controle sobre a memória nativa e como chamadas nativas são formadas. Em alguns casos, pode ser usada como substituta da JNI. Com essas novas APIs, podemos criar uma integração profunda entre o tempo de execução e o gerenciamento de memória do Java e do Swift. De outra forma, isso não teria sido possível. Isso resulta em melhor segurança e desempenho ao fazer chamadas nativas do Java. Aqui, usaremos o tipo struct Swift que representa um objeto de negócios que eu gostaria de expor ao Java. É um tipo de valor, não tem uma identidade de objeto estável, o que não é algo que os objetos Java possam expressar. Por isso, teremos que ser cuidadosos ao lidar com esse objeto em Java. Ele tem uma propriedade pública, um inicializador e alguns métodos para operá-lo. Para expor esse tipo ao Java, usaremos a ferramenta de linha de comando Swift-Java novamente. Desta vez, vamos usá-la de uma forma um pouco diferente. Forneceremos um caminho de entrada Swift e diretórios de saída para as fontes Swift e Java geradas. A ferramenta pegará todas as fontes do caminho de entrada e gerará classes Java, que serão acessadores para tipos e funções do Swift. Geraremos alguns códigos auxiliares do Swift necessários. Tudo, incluindo o código do Swift criado como uma biblioteca dinâmica, será compilado e empacotado em uma biblioteca Java. A classe Java gerada será mais ou menos assim. Ela implementa a interface de valor do Swift porque era um Struct. A classe contém um segmento de memória self, que é um ponteiro para a instância na memória nativa. Ela representa os inicializadores públicos, propriedades e funções usando as assinaturas Java equivalentes. Dentro deles, temos código altamente eficiente gerado pela fonte para fazer chamadas nativas usando as APIs Foreign Function. Dentro do app Java, podemos depender das fontes do Java geradas. Para criar e gerenciar valores Swift nativos, precisaremos de uma SwiftArena, que cuida da alocação de memória e do ciclo de vida de objetos do Swift. Com uma arena preparada, podemos invocar o construtor de valores do Swift como se fosse uma classe Java normal. Vamos discutir um pouco mais como os recursos de memória nativa e Java estão sendo gerenciados aqui. Primeiro, um novo objeto wrapper Java é alocado no heap Java, que é gerenciado pelo coletor de lixo da JVM. O construtor gerado pela fonte então usa a SwiftArena passada para alocar e inicializar uma instância do tipo de valor do Swift no heap nativo. Normalmente, tipos de valor como o struct SwiftyBusiness são alocados na pilha, mas como precisamos de um endereço de memória estável, ele é alocado no heap. Isso permite apontar com segurança para esse endereço no objeto wrapper Java. Eventualmente, o wrapper Java não é mais usado, e o Coletor de Lixo decidirá coletá-lo e destruí-lo. Isso acionará uma destruição da instância nativa no Swift também. Para gerenciamento de memória, isso é seguro. Diferentemente do Swift, depender da finalização de objetos coloca muita pressão sobre o GC devido ao rastreamento adicional necessário nesses objetos. Isso também resulta em um tempo imprevisível do valor Swift nativo sendo desinicializado. Embora seja um padrão fácil para começar, vou mostrar uma forma melhor de gerenciar a memória nativa. Em vez de uma Auto Arena, podemos usar uma sintaxe Java try-with-resources em combinação com o tipo Confined Arena. A alocação de objetos ocorrerá da mesma forma aqui, no entanto, try-with-resources muda como os objetos são destruídos. Especificamente, ao final do escopo triplo, a Arena será fechada. Isso aciona a destruição do objeto wrapper Java que, por sua vez, aciona a destruição do valor do Swift no heap nativo. Essa abordagem é muito melhor. Não oneramos o GC com a finalização de objetos, que pode ser problemática em grandes quantidades. Recuperamos a propriedade de desinicialização de objetos definida e ordenada, da qual muitas atividades do Swift dependem. Quando possível, use Scoped Arenas, em vez de usar o GC para o melhor comportamento e desempenho no app. Para recapitular, conseguimos encapsular uma biblioteca Swift completa com uma única invocação da ferramenta de linha de comando Swift-Java. Criamos bibliotecas Swift encapsuladas como Java e as publicamos, facilitando o consumo delas em projetos do Java e simplificando mais a adoção do Swift em suas equipes. Ao usar as modernas APIs Foreign Function and Memory, controlamos rigorosamente as alocações de objetos e os ciclos de vida, mesmo de tipos de valor do Swift. Abordamos muitas técnicas diferentes para trabalhar com Swift e Java, e você pode usá-los de forma independente ou em conjunto, dependendo das necessidades do seu projeto. Estamos apenas começando e há muito a ser polido e refinado, mas o SwiftJava já oferece uma ótima abordagem para a interoperabilidade entre essas linguagens. Usando as bibliotecas de suporte SwiftKit e JavaKit, você pode escrever código seguro e eficiente que use uma linguagem na outra. As macros JavaKit e o Swift-Java geram automaticamente qualquer código repetitivo que, de outra forma, seria difícil de manter.
Por fim, quero convidar você a participar do desenvolvimento deste projeto. É completamente de código aberto e está disponível na organização swiftlang do Github. Há muitos desafios empolgantes para resolver e ideias para explorar. Se não sentir segurança para contribuir, mas quiser saber mais sobre o Swift e o Java ou compartilhar ideias e comentários, participe dos fóruns do Swift. Agradeço sua participação. Quanto a mim, acho que vou tomar um café.
-
-
9:05 - Implement JNI native methods in Swift
import JavaKit import JavaRuntime import Crypto @JavaImplementation("com.example.JNIExample") extension JNIExample: JNIExampleNativeMethods { @JavaMethod func compute(_ a: JavaInteger?, _ b: JavaInteger?) -> [UInt8] { guard let a else { fatalError("Expected non-null parameter 'a'") } guard let a else { fatalError("Expected non-null parameter 'b'") } let digest = SHA256Digest([a.intValue(), b.intValue()]) // convenience init defined elsewhere return digest.toArray() } }
-
12:30 - Resolve Java dependencies with swift-java
swift-java resolve --module-name JavaApacheCommonsCSV
-
13:05 - Use a Java library from Swift
import JavaKit import JavaKitIO import JavaApacheCommonsCSV let jvm = try JavaVirtualMachine.shared() let reader = FileReader("sample.csv") // java.io.StringReader for record in try JavaClass<CSVFormat>().RFC4180.parse(reader)!.getRecords()! { for field in record.toList()! { // Field: hello print("Field: \(field)") // Field: example } // Field: csv } print("Done.")
-
16:22 - Wrap Swift types for Java
swift-java --input-swift Sources/SwiftyBusiness \ --java-package com.example.business \ --output-swift .build/.../outputs/SwiftyBusiness \ --output-java .build/.../outputs/Java ...
-
18:55 - Create Swift objects from Java
try (var arena = SwiftArena.ofConfined()) { var business = new SwiftyBusiness(..., arena); }
-
-
- 0:00 - Introdução
Conheça uma biblioteca experimental da linguagem Swift, chamada swift-java, que permite que o Swift funcione perfeitamente com o Java, aproveitando os recursos já existentes de interoperabilidade com Objective-C, C e C++. Essa interoperabilidade permite introduzir o Swift de forma incremental em bases de código Java atuais, reutilizar bibliotecas entre linguagens e integrar bibliotecas Swift em projetos Java. A interoperabilidade oferecida pelo swift-java permite tanto chamar código Java no Swift, e vice-versa. A equipe está trabalhando em ferramentas e técnicas para lidar com as diferenças entre os tempos de execução entre Java e Swift, além de oferecer maior segurança de memória para código Java traduzido em tipos do Swift.
- 2:41 - Diferenças nos tempos de execução
As linguagens Swift e Java têm recursos em comum, como classes, herança, gerenciamento automático de memória, genéricos e tratamento de erros, embora existam diferenças nos tempos de execução. Apesar dessas diferenças, as semelhanças entre as duas linguagens permitem expressar a maioria das APIs de uma linguagem na outra.
- 3:31 - Métodos nativos do Java
A API Java Native Interface (JNI) foi lançada no início de 1997 e permite que o código Java em execução dentro de uma Java Virtual Machine (JVM) interopere com código nativo, como Swift. Isso geralmente é feito para melhorar o desempenho ou utilizar bibliotecas nativas que não têm equivalente em Java. Para usar a JNI, uma função native é definida em Java e é gerado um arquivo de cabeçalho em C correspondente. Esse arquivo contém uma declaração de função em C que deve ser implementada na linguagem nativa, como Swift. O processo envolve o gerenciamento do ciclo de vida de objetos, a correspondência de assinaturas de métodos e o tratamento de código repetitivo e longo, o que pode ser suscetível a erro e, demorado, além de levar a falhas fatais.
- 6:29 - Swift-Java
O SwiftJava melhora a interoperabilidade entre as linguagens Swift e Java. Ele oferece um pacote de ferramentas, incluindo bibliotecas Swift e Java, uma ferramenta de linha de comando e integrações com sistemas de compilação, para simplificar e tornar mais segura a interação entre as duas linguagens. A ferramenta de linha de comando swift-java automatiza a geração do código de ligação, eliminando a necessidade de lidar manualmente com arquivos de cabeçalho em C. Isso resulta em um código mais limpo, fácil de manter, com melhor gerenciamento do ciclo de vida dos objetos e maior segurança de tipos. Agora você pode se concentrar na lógica de negócios, aproveitando ao máximo os ecossistemas do Swift e do Java e evitando os erros e armadilhas comuns da implementação manual da JNI.
- 10:13 - Chamar o Java no Swift
O SwiftJava permite integrar bibliotecas Java a projetos do Swift. Para importar uma biblioteca Java inteira, como a Apache Commons CSV, prepare as seguintes coordenadas de artefato: groupId, artifactId e version. Em seguida, o SwiftJava utiliza o Gradle, um sistema de compilação de código aberto, para resolver dependências Java. Existem duas formas de baixar e encapsular essas dependências: Usando o plug-in da ferramenta de compilação SwiftJava, que requer a desativação do Sandbox de segurança do SwiftPM, ou o comando resolve da ferramenta de linha de comando swift-java, que executa a resolução fora do processo de compilação. Após resolver as dependências do Java, você pode importar a biblioteca Java no Swift, iniciar a JVM dentro do processo do Swift e usar o código em Java e suas coleções de forma integrada com os recursos do Swift, com o JavaKit gerenciando o ciclo de vida dos objetos.
- 14:01 - Chamar o Swift no Java
O SwiftJava permite integrar bibliotecas Swift a projetos do Java. Para isso, esta sessão da WWDC25 apresenta uma nova abordagem que elimina a necessidade de funções de wrapper extensas no lado Java. Em vez disso, toda a biblioteca Swift é encapsulada com classes Java utilizando a nova API Foreign Function and Memory (FFI), introduzida no Java 22. A FFI oferece controle aprimorado sobre a memória nativa e permite uma integração profunda entre os tempos de execução e sistemas de gerenciamento de memória do Java e do Swift. Ao usar a FFI, o processo de chamar o código do Swift a partir do Java fica mais eficiente e seguro. A ferramenta de linha de comando swift-java é usada para gerar as classes Java necessárias e o código auxiliar em Swift. Ela automatiza a geração de código padrão, simplificando o processo. As classes Java geradas funcionam como assessores para os tipos e funções Swift, expondo efetivamente a funcionalidade da biblioteca Swift para o Java. O gerenciamento adequado de memória é fundamental ao trabalhar com objetos Swift nativos em Java. A discussão destaca duas abordagens: O uso do AutoArena, que depende do Coletor de Lixo (GC) do Java, e o método preferido, que utiliza o bloco try-with-resources com o ConfinedArena. Essa última abordagem garante uma desalocação de objetos bem definida e ordenada, evitando problemas de desempenho e sobrecarga no GC. Essa técnica permite criar e publicar bibliotecas Java encapsuladas em Swift, facilitando sua utilização em projetos do Java. Isso simplifica a adoção do Swift por equipes que já possuem uma base sólida em Java, promovendo um ambiente de desenvolvimento mais flexível e eficiente. O desenvolvimento contínuo do SwiftJava busca aprimorar ainda mais essas técnicas, oferecendo uma solução robusta para a interoperabilidade entre as duas linguagens.
- 20:47 - Conclusão
A linguagem de programação Swift é de código aberto e hospedada no GitHub e em bibliotecas como o SwiftJava. A comunidade é ativa nos fóruns do Swift, onde você pode aprender, compartilhar ideias e dar feedback.