18 · Módulos
Java com extern
Java 8 em diante, objetos com identidade e bibliotecas Maven pelo provider JVM.
Nesta página
Importe java do plugin jvm. As assinaturas das funções usam tipos Zolo,
enquanto os corpos usam Java. Chame as funções diretamente, com a mesma sintaxe
das outras funções Zolo. Estes exemplos executam pelo CLI com o plugin JVM
instalado; o Playground do navegador não hospeda uma JVM.
Use um import Java no início do corpo, retorne um inteiro exato e aguarde um CompletableFuture.
use plugin jvm::{java}
extern java fn upper(value: str) -> str {
import java.util.Locale;
return value.toUpperCase(Locale.ROOT);
}
extern java fn exact(value: int) -> int {
return value;
}
extern java async fn later(value: int) -> int {
import java.util.concurrent.CompletableFuture;
return CompletableFuture.supplyAsync(() -> value + 1L);
}
print(upper("hello Java"))
print(exact(9007199254740993))
print(await later(41))
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
HELLO JAVA
9007199254740993
42
int e i64 correspondem a long em Java, preservando inteiros de 64 bits
com sinal, inclusive valores acima de 2^53. i32 corresponde a int em Java;
os tipos menores mantêm seus tipos nativos. Use 1L para um literal long em
Java. Os overloads seguem os tipos declarados, e conversões que estouram o
intervalo ou perdem precisão geram um erro.
extern java async fn transforma um CompletionStage<T> Java em uma Future
Zolo. Use await normalmente. Interfaces funcionais Java podem receber
callbacks Zolo; callbacks de threads Java voltam ao executor responsável pelo
código Zolo. Cancelar uma Future solicita o cancelamento, mas o trabalho Java
que ignora interrupções pode continuar executando.
Arquivos, JARs e objetos
Importe a classe pública Person de um arquivo Java usando um alias do provider. Construa com .new, chame métodos, altere um campo e passe a mesma instância para uma função inline separada.
use plugin jvm::{java as j}
extern j from "./java_fixtures/Person.java" use {Person}
extern j fn same(person: Person) -> Person { return person; }
let person = Person.new(name: "João", age: 30)
print(person.getName())
print(person.getAge())
person.age = 31
print(person.age)
print(Person.twice(21))
print(person == same(person))
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
João
30
31
42
true
Os caminhos partem do arquivo Zolo que faz o import. O arquivo auxiliar
java_fixtures/Person.java expõe construtores e métodos públicos, além do campo
público gravável age. Os objetos mantêm a identidade e o estado nativos;
passar um objeto entre essas funções não copia seus campos.
Um JAR local usa a mesma forma de import:
extern java from "./Person.jar" use {Person}. Com um JAR que exponha a mesma
API pública, let person = Person.new("João", 30) seguido de
print(person.getName()) imprime João. Use argumentos posicionais para
bindings de JAR quando os nomes dos parâmetros não estiverem disponíveis.
Imports de código-fonte expõem os nomes para chamadas com argumentos nomeados.
JARs que incluem o atributo MethodParameters, normalmente produzido por
javac -parameters, também preservam esses nomes: a mesma classe permite
Person.new(name: "João", age: 30).
Use APIs Java públicas entre módulos compilados separadamente. O acesso package-private exige arquivos-fonte compilados juntos. Para varargs, generics abertos ou um tipo nativo não suportado, exponha um pequeno wrapper Java com assinatura concreta. Campos estáticos também precisam de um wrapper nesta versão.
Bibliotecas Maven
Declare cada dependência uma vez no escopo do arquivo. As funções Java mantêm seus imports normais, e Maven resolve o grafo transitivo de JARs antes de compilar.
Fixe a versão do Guava pela coordenada Maven group:artifact e use Joiner no Java.
// Prepare with `zolo install` or opt into `zolo run ... --install=auto`.
use plugin jvm::{java}
extern java deps {
"com.google.guava:guava" = "33.4.0-jre"
}
extern java fn join(values: [str]) -> str {
import com.google.common.base.Joiner;
return Joiner.on(", ").join(values);
}
print(join(["Java", "Maven", "Zolo"]))
Requer a CLI/host do Zolo — abra no playground ou rode localmente.
Java, Maven, Zolo
Para um script independente chamado analysis.zolo, permita preparar os pacotes
na primeira execução com zolo run analysis.zolo --install=auto. Para instalar
explicitamente:
zolo install analysis.zolo
zolo run analysis.zolo --install=manual
zolo run analysis.zolo --offline --frozen
Scripts independentes usam auto; projetos usam manual. O lock do script é
analysis.zolo.lock. --offline usa somente o cache local, enquanto --frozen
exige um lock correspondente e impede alterações nele. Abrir um arquivo no
editor não baixa dependências nem executa o código Java escrito pelo autor.
Nos projetos, mova a declaração da dependência para o zolo.toml e mantenha a
função Java e seu import no main.zolo:
[package]
name = "java-demo"
version = "0.1.0"
[packages]
schema = 2
[foreign]
install = "manual"
[foreign.jvm.dependencies]
"com.google.guava:guava" = "33.4.0-jre"
Execute zolo install main.zolo, depois zolo run main.zolo --offline --frozen.
O projeto usa zolo.lock. Declarações iguais no código e no manifesto se
combinam; requisitos conflitantes apontam suas origens. Declarações Maven
diretas aceitam versões exatas ou intervalos nativos. Campos diretos para BOM,
classifier, scope e exclusion ainda não são expostos.
Escolher o Java e distribuir
A compilação do código-fonte e os recursos semânticos do editor exigem um JDK 8
ou mais recente. Configure ZOLO_JAVA_HOME antes da primeira chamada Java;
JAVA_HOME funciona como alternativa. A arquitetura da JVM precisa ser igual
à do Zolo. Os runtimes Java são instalados separadamente. O código usa Java 8
como alvo padrão, mesmo com um JDK mais recente. Configure ZOLO_JAVA_RELEASE,
por exemplo com 17, para usar uma versão mais recente da linguagem e suas
APIs; o compilador selecionado precisa suportar esse alvo.
VM, native e LLVM executam o mesmo provider. Os artefatos compilados guardam classes, JARs das dependências, recursos e mapas do código-fonte. As formas de distribuição dynamic, embed e static podem executar sem os fontes originais ou um compilador Java. A distribuição ainda exige uma JRE compatível com o alvo selecionado e todas as dependências; empacotar o plugin não inclui Java. Bibliotecas com binários nativos mantêm seus requisitos de plataforma. A execução de uma JVM hospedada não está disponível no wasm-aot.
Exceções Java funcionam com try/catch e apontam para o código-fonte escrito
pelo autor. Nas bibliotecas que usam um common pool existente ou outro executor,
propague o class loader de contexto da sessão ou informe-o explicitamente nas
buscas de recursos e serviços. Consulte o guia do plugin JVM para esses detalhes.
A validação atual cobre Windows x64 com JDK 8, 11 e 23, além da distribuição
com JRE 8 sem compilador; Linux e macOS ainda precisam de validação em execução.
Veja também