Referenciando bibliotecas para um executável Linux
-
21-09-2019 - |
Pergunta
Eu escrevi um aplicativo em Java e o compilei com sucesso usando gcj.Funcionou surpreendentemente bem, mas me deparei com um obstáculo:Só posso executar o executável por meio de um script de shell, porque preciso especificar os caminhos da biblioteca.
As bibliotecas que preciso são SWT, Xerces e GNU-crypto.
Existe uma maneira de vincular estaticamente as bibliotecas ao compilar em gcj
, ou isso não é uma boa ideia?Alternativamente, posso especificar o caminho da biblioteca (relativa) durante a compilação?
Atualmente, meu script de shell está assim:
#!/bin/sh
export LD_LIBRARY_PATH=./libs/:$LD_LIBRARY_PATH
exec ./MyJavaApp $*
Solução
A idéia é fazer o campo estático "sys_paths" nulo para que ele construísse os caminhos a partir do valor alterado. Veja o post aqui (Post#223 por Ajaysingh516) http://forums.sun.com/thread.jspa?messageId=3744346#3744346
Class clazz = ClassLoader.class;
Field field = clazz.getDeclaredField("sys_paths");
boolean accessible = field.isAccessible();
if (!accessible)
field.setAccessible(true);
Object original = field.get(clazz);
// Reset it to null so that whenever "System.loadLibrary" is called, it
// will be reconstructed with the changed value.
field.set(clazz, null);
try {
// Change the value and load the library.
System.setProperty("java.library.path", "./libs/");
System.loadLibrary("mylibapr");
} finally {
// Revert back the changes.
field.set(clazz, original);
field.setAccessible(accessible);
}
.
Propriedades do sistema GCJ (Veja: Propriedades padrão suportadas pela libgcj)
http://gcc.gnu.org/onlinedocs/gcj/system-properties.html
.
Solução#2: Defina a variável do ambiente do sistema no tempo de compilação
http://linux.die.net/man/1/gcj
Para isso, você tem que usar o parâmetro -Djava.library.path=./libs/
com gcj
Do manual do GCJ (acima do link):
--main = ClassName
Esta opção é usada ao vincular para especificar o nome da classe cujo método "principal" deve ser chamado quando o executável resultante for executado.
-Dname [= valor
Esta opção só pode ser usada com "--principal". Ele define uma propriedade do sistema nomeada nome com valor de valor. Se o valor não for especificado, o padrão é o padrão da string vazia. Essas propriedades do sistema são inicializadas na inicialização do programa e podem ser recuperadas em tempo de execução usando o método "java.lang.system.getproperty".
Eu nunca trabalhei com o GCJ, mas, de acordo com os documentos, essas propriedades do sistema podem ser recuperadas em tempo de execução, portanto, também será portátil para outros sistemas.
Veja também: http://gcc.gnu.org/wiki/statics_linking_libgcj?action=show&redirect=staticsaticsticslinking+libgcj
Outras dicas
Para responder à primeira parte da sua pergunta -
Na página de manual do gcj:"A vinculação estática da libgcj pode fazer com que partes essenciais da libgcj sejam omitidas.Algumas partes da libgcj usam reflexão para carregar classes em tempo de execução.Como o vinculador não vê essas referências no momento do link, ele pode omitir as classes referidas.O resultado geralmente (mas nem sempre) é uma "ClassNotFoundException" lançada em tempo de execução.Deve-se ter cuidado ao usar esta opção."
Para a vinculação estática das outras bibliotecas, não tenho certeza.Eu não tive uma razão para fazer isso.
Os executáveis do Linux são diferentes do Windows.Normalmente você tem um "iniciador" ou algo assim, dependendo de qual sistema de janelas exato você está usando.Você define o ícone nisso, não no próprio executável.Normalmente, os scripts de inicialização são usados para definir qualquer ambiente necessário para executar o executável.Novamente, tudo isso depende do sistema exato de janelas da sua área de trabalho.
Por que você está usando um AOT? Eu sugeriria ler o Artigo a seguir. Uma das desvantagens que ele menciona para AOTS é o seguinte ...
Aplicações dinâmicas. As classes que o aplicativo carrega dinamicamente em tempo de execução podem não estar disponíveis para o desenvolvedor do aplicativo. Estes podem ser plug-ins de terceiros, proxies dinâmicos e outras classes geradas em tempo de execução e assim por diante. Portanto, o sistema de tempo de execução deve incluir um intérprete Java Bytecode e/ou um compilador JIT.