O que impede o Java de obter portabilidade no nível C?

4

Em que portabilidade é definida geralmente como a porcentagem de plataformas em que uma linguagem ou tecnologia pode ser executada, C / C ++ são frequentemente citados como sendo mais portáveis do que Java, porque um aplicativo Java depende de uma JVM presente.

Mas, o que impede que um aplicativo Java envie dentro de um wrapper da JVM? Ou sendo transpilado para C / C ++ com uma estrutura de suporte? (Essencialmente uma JVM, mas como uma biblioteca de suporte em vez de um wrapper / container.)

Existe algum problema técnico? Um problema de licenciamento? Ou simplesmente que ninguém decidiu fazê-lo!

Tomando um exemplo concreto, considere o segundo item da primeira resposta a " Por que o Java não é mais amplamente usado para desenvolvimento de jogos? ", que afirma que:

Most consoles (e.g., 360, PS3) do not have a JVM, so you cannot reuse code from the PC version. It is much easier to compile C++ code to support various devices.

Se esta afirmação é correta (com relação aos "mais" consoles), a falta da JVM para essas plataformas deve-se a limitações técnicas? Legal? Político? etc.

Quando é declarado que Java "não pode" ser executado em consoles de jogos (ou iPhones), realmente queremos dizer não pode! Ou, queremos dizer, "ninguém está incomodado em construir o encanamento necessário? "

    
por svidgen 26.01.2018 / 18:21
fonte

5 respostas

13

O Java é portátil no sentido de que C ou C ++ podem ser portáveis: o mesmo código-fonte pode ser usado para vários sistemas operacionais ou arquiteturas de processadores. Na verdade, isso é muito mais fácil em Java, já que a JVM abstrai vários detalhes específicos da plataforma (como o tamanho de long int ou endianness) e a biblioteca padrão abstrai a funcionalidade fornecida pelo sistema operacional (por exemplo, como para abrir um arquivo).

Para C e C ++, a próxima melhor coisa é manter o padrão POSIX, que pelo menos lhe dá portabilidade de origem entre Unixes e Linux, mas exclui, principalmente, o Windows sem o WSL ou o Cygwin. E, diferentemente do Java, uma base de código portátil deve ser recompilada para cada plataforma de destino. O que torna C e C ++ “mais portáteis” é que cross-compilers como o GCC tendem a ter muitas plataformas de destino (para suportar um novo target, você “só” precisa criar um novo backend de compilador).

O Java 9 introduz a possibilidade de transformar um aplicativo Java em um executável independente que inclua todas as partes necessárias do Java Runtime. Mas você ainda está limitado pela portabilidade de sua JVM. E o pacote precisa ser construído no sistema operacional de destino.

A JVM em si é um programa que pode ou não ser portável. Por exemplo. O HotSpot é um programa C ++ que pode ser portado para novos sistemas operacionais ou arquiteturas.

Mas e se estivermos segmentando um dispositivo incorporado que talvez não execute um sistema operacional completo ou tenha restrições de hardware? Isso se torna mais difícil para C e Java. Mas existem JREs incorporados e, para ambas as classes de idiomas, a solução envolve a segmentação de uma biblioteca padrão menor. O Java 9 torna possível selecionar módulos no momento da compilação, em vez de ter que direcionar um perfil predefinido como o Java ME.

Um caso de uso em que C ganha está funcionando em ausência de um sistema operacional, exibido diretamente em um microcontrolador. Você não pode usar a biblioteca padrão (por exemplo, para abrir arquivos ou alocação de memória dinâmica), mas o idioma principal ainda está lá. Mas não é razoável restringir o significado de “portabilidade” para “pode funcionar sem a biblioteca padrão”.

Sistemas bloqueados, como iOS ou consoles, não permitem a instalação de software arbitrário, mesmo que sejam fisicamente capazes de executar esse software - eles geralmente são construídos a partir de CPUs padrão, usando kernels padrão. A ausência de uma JVM nesses sistemas é apenas uma conseqüência do gatekeeper (por exemplo, Apple ou Nintendo) não estar interessado em permitir uma plataforma separada que não esteja sob seu controle. Então essa ausência é legal / política.

    
por 26.01.2018 / 19:06
fonte
6

a Java application depends on a JVM being present.

Isso não é verdade. Não há nada na Especificação da Linguagem Java que diga algo sobre a JVM. A Oracle é bastante rigorosa em manter os dois separados.

E, de fato, há uma plataforma de celular bastante popular do Google que usa o Java extensivamente sem uma JVM.

But, what prevents a Java application from shipping within a JVM wrapper? Or being transpiled to C/C++ with a supporting framework? (Essentially a JVM, but as a supporting library instead of a wrapper/container.)

Nada.

Is there a technical issue? A licensing issue? Or, simply that no one has decided to do it!?

Sim.

Most consoles (e.g., 360, PS3) do not have a JVM, so you cannot reuse code from the PC version. It is much easier to compile C++ code to support various devices. If this claim is correct (with regards to "most" consoles), is the lack JVM for these platforms due to technical limitations?

Não.

Legal? Political? etc.

Provavelmente.

Ou apenas ninguém fez o trabalho ainda.

When it's stated that Java "can't" be run on game consoles (or iPhones), do we really mean can't!? Or, do we mean, "no one's bothered build the necessary plumbing?"

A Apple não permite aplicativos que possam executar códigos que não fazem parte do aplicativo. Isso tornaria uma JVM pura inútil.

Note, claro, que você pode ter um aplicativo que inclua o código do aplicativo e uma JVM em um aplicativo. Mas todo aplicativo precisaria ter sua própria cópia da JVM.

    
por 26.01.2018 / 23:28
fonte
2

But, what prevents a Java application from shipping within a JVM wrapper?

Acho que você entendeu errado: se houver uma implementação da JVM, a batalha já será vencida, independentemente de a dita JVM ser enviada separadamente ou incorporada ao aplicativo. O problema é escrever a JVM em primeiro lugar.

Como um aparte, quando as pessoas falam sobre "portabilidade", elas geralmente significam "você pode recompilar este código fonte com poucas mudanças e fazê-lo funcionar em outra plataforma", não apenas "há um compilador para esta plataforma" ( embora, é claro, o último seja um requisito). Nesse sentido, Java é tão portátil quanto C, ou seja: código simples provavelmente será executado como está, mas algumas bibliotecas podem estar indisponíveis e algumas suposições sobre a memória podem estar equivocadas. Note que, embora provavelmente exista uma implementação do compilador C para quase todas as plataformas, muitos programas C não-triviais não podem funcionar em outra plataforma meramente recompilando, por causa de APIs, bibliotecas, suposições de memória e outras dependências. / p>

When it's stated that Java "can't" be run on game consoles (or iPhones), do we really mean can't!? Or, do we mean, "no one's bothered build the necessary plumbing?"

Não há razão técnica para o Java não rodar no iPhone, no Nintendo Switch ou em qualquer console. Se não houver uma implementação da JVM, isso geralmente significa que existem razões legais (o que provavelmente é o caso do iPhone e do hardware proprietário com SDKs oficiais), ou não faz sentido porque já existe um SDK amplamente usado com bibliotecas úteis para outro idioma, ou ambos.

    
por 26.01.2018 / 20:49
fonte
2

TL; DR : Além das questões legais / comerciais que outros já mencionaram, há limitações técnicas. Grosso modo, criar uma JVM razoavelmente boa é mais difícil que um razoavelmente bom compilador C. Então, embora, teoricamente, seja possível, muitas portas não são criadas simplesmente devido ao esforço necessário.

Então, quais são os desafios? Existem pelo menos três elementos importantes de uma implementação Java em funcionamento: suporte para analisar e compilar a própria linguagem, implementar a biblioteca padrão e fazer a JVM que oferece uma ambiente no qual os aplicativos compilados são executados.

Quanto à linguagem, o Java tem muitos recursos que faltam a , como a orientação a objetos, muita validação imposta pela especificação da linguagem (verificação de limites de matriz, validação de código antes que as classes sejam carregadas, etc. .), um gerenciador de segurança, carregamento de classes de tempo de execução, um modelo de memória que diz com precisão como o código multi-thread deve se comportar, e algumas outras características obscuras que muitos desenvolvem nem percebem descreve em grande detalhe. Tudo isso faz com que diferentes implementações de Java sejam muito mais semelhantes entre si em termos de comportamento de programa do que diferentes compiladores de C, mas isso tem o custo de entender e implementar muitos e muitos recursos.

Depois, há a biblioteca padrão , que também é bastante rica. A maioria é escrita em Java, mas também há algum código nativo usado por motivos de desempenho ou porque a biblioteca trabalha em um nível baixo que não está disponível diretamente do Java puro, não para as bibliotecas (por exemplo, a simultaneidade de baixo nível). código).

E finalmente há a JVM que é um monstro infernal . Ele executa várias operações que são muito complexas de implementar e ainda mais difíceis de implementar corretamente: coleta de lixo, compilação just-in-time, carregamento e descarregamento de classes, interface com código nativo e, ao mesmo tempo, preserva a integridade da JVM. Dê uma olhada em Uma JVM faz isso? para obter uma lista parcial. Implementar tudo isso enquanto mantém o alto desempenho é uma tarefa muito difícil e há muito poucas pessoas realmente capazes de fazer isso.

Além da complexidade da implementação, há também alguns custos de desempenho . Embora os programas Java possam ser realmente rápidos hoje em dia, isso é possível apenas graças a muitos truques muito inteligentes implementados pela JVM. Implementar uma JVM sem as otimizações faria com que todos os programas rodassem lentamente e, assim, tornassem a porta inteira um tanto quanto inútil. Há também alguma sobrecarga de memória que é difícil de evitar. Este não é um grande problema para um PC ou servidor, mas para ambientes mais restritos é. Há também muitos dados que a própria JVM precisa: toda a biblioteca padrão complexa. Ou o banco de dados Unicode que tem pelo menos vários megabytes de tamanho, se não me engano.

Claro que se não é tão fácil fazer uma JVM para uma nova plataforma, também é tão difícil fazer um transpiler ou algo que compila Java para binários nativos, já que os binários têm que conter a JVM ou grandes suas partes.

No Java 9, o foco principal era a modularização , o que significa que, pela primeira vez, seu programa hello world pode não precisar incluir 50 MB de bibliotecas apenas para o início da JVM. Este é um passo importante na direção certa, mas ainda há um longo caminho a percorrer antes que o Java real possa ser executado em ambientes restritos como o C. O J2ME é, na verdade, apenas um subconjunto da pilha Java completa.

    
por 27.01.2018 / 10:17
fonte
1

Tamanho e velocidade são dois fatores enormes. Uma JVM é um programa bastante grande que precisa de muita memória RAM e espaço de armazenamento para ser usado. Uma JVM também é geralmente mais lenta (dependendo do fluxo de trabalho).

Isso significa que o Java não é adequado para programação embutida (claro, dependendo de quão pequeno você acha que é incorporado). Por exemplo, tente executar o java em um microcontrolador de 8 bits, por exemplo, um arduino.

Editar:

Java Card é um subconjunto (!) do java com requisitos mínimos de sistema de 16 kB ROM, 8 kB EEPROM e 256 bytes RAM. Embora isso seja pequeno, não é tão pequeno quanto o C pode gerenciar. É realmente muito inchado. O Java Card usa aritmética de 16 bits, o que significa que ele não será executado (bem) em uma CPU de 8 bits.

Para o J2ME, os requisitos são ainda maiores, então deixo esse fora de discussão.

Por favor, não faça downvote esta resposta sem provar que minha declaração está errada, isto é, mostre-me o java rodando em um sistema de 8 bits altamente restrito.

    
por 26.01.2018 / 18:42
fonte