A JVM suporta tantas linguagens que não Java, como Groovy,Clojure,Scala
etc, que são linguagens funcionais diferentes do Java (refiro-me ao Java antes da Versão 8, onde Lambda's
não são suportadas) que não suportam recursos funcionais. Em um alto nível, o que torna a JVM tão versátil que pode suportar idiomas orientados a objetos e funcionais?
18
Respostas:
Comparada a outras VMs, a JVM na verdade não é particularmente versátil . Ele suporta diretamente OO digitado estaticamente. Para todo o resto, é necessário ver quais partes você pode usar e como criar tudo o que seu idioma precisa sobre essas partes.
Por exemplo, até que o Java 7 introduzisse o
invokedynamic
bytecode, era muito difícil implementar uma linguagem OO de tipo dinâmico na JVM - era necessário usar soluções alternativas complexas que apresentavam problemas de desempenho e resultavam em rastreios de pilha horrivelmente inchados.E, no entanto, várias linguagens dinâmicas (Groovy, Jython, JRuby entre outras) foram implementadas na JVM antes disso.
Não porque a JVM é muito versátil, mas porque é muito difundida e porque possui implementações muito maduras, bem suportadas e de alto desempenho.
E, talvez ainda mais importante, porque há uma enorme quantidade de código Java por aí fazendo praticamente qualquer coisa e, se sua linguagem é executada na JVM, você pode oferecer facilidades facilmente para integrar-se a esse código. Basicamente, ter seu idioma rodando na JVM é a versão do século XXI de oferecer interoperabilidade com C.
fonte
A JVM foi escrita para agir basicamente como uma CPU, há um conjunto de instruções, como o assembly, que a VM executa chamado bytecodes. Se você puder gravar um compilador que gere um conjunto válido de bytecodes, a JVM poderá executá-los.
A Wikipedia possui uma lista dos bytecodes:
http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
bem como uma explicação de como a JVM carrega os códigos de bytes:
http://en.wikipedia.org/wiki/Java_virtual_machine
Ao usar os bytecodes de estilo de chamada, uma linguagem funcional pode executar código, independentemente da aparência da fonte. Além disso, com a adição de invokevirtual, implementações de linguagem como o jruby têm proporcionado alguma flexibilidade na forma como são executadas.
fonte
Acrescentarei que a JVM suporta um JMM (Modelo de Memória ) bem definido e bastante decente, o que significa um bom suporte para um comportamento de encadeamento consistente (embora de baixo nível). Ele também possui um poderoso compilador Just In Time (não é mais útil para linguagens dinâmicas, graças a MethodHandles e invokedynamic).
Por último, mas não menos importante, é o subsistema de coleta de lixo da JVM que (com o ajuste correto) gerencia a memória para você, independentemente do idioma no topo.
fonte
someField = new int[]{42};
as únicas maneiras de garantir que qualquer thread que veja a nova matriz veja o valor 42 são para fazer o campofinal
ouvolatile
. Se o campo for gerado preguiçosamente, mas acessado com frequência,final
não funcionará evolatile
poderá impor uma penalidade de sincronização desnecessária toda vez que for acessado. Até mesmo no mais fraco modelo .NET ... #O elemento chave nisso é a separação da compilação da fase de execução. Com isso, é possível escrever outros compiladores compilando outros idiomas no bytecode.
O bytecode atua de maneira semelhante ao código de máquina de uma CPU - você tem todas as pequenas operações necessárias para executar um programa - você pode obter uma variável, fazer contas nela, realizar operações condicionais etc.
Java também não é especial. Em Java, a existência de várias linguagens não era nem uma meta de design, ao contrário de outras VMs. Para o .Net CIL da Microsoft, a capacidade de executar vários idiomas (C #, VB.Net, ...) era um elemento-chave de design, também o ParrotVM do projeto Perl6 pretendia ser uma VM genérica.
Por diversão, criei uma prova de que até o Zend Engine do PHP permitiria isso.
E, francamente, isso não é novidade - mesmo em hardware real, você pode executar vários idiomas - ou seja, C ou Fortran.
A diferença para essa separação da compilação e execução são os intérpretes clássicos, como algumas formas de Basic, scripts de shell etc. Eles geralmente funcionam de maneira a executar código mais ou menos linha por linha, sem trazê-lo de forma imediata. entre.
fonte
A JVM é a primeira máquina virtual que eu conheço, que combina coleta de lixo, desempenho e um modelo de sandbox viável. O surgimento de muitas linguagens para suportar a JVM provavelmente não resulta tanto de sua "versatilidade", mas do fato de a linguagem Java carecer de alguns recursos significativos que as pessoas desejam em uma linguagem de programação. Por exemplo, enquanto a maioria das linguagens de máquina possui apenas meia dúzia de tipos de dados (por exemplo, byte, meia palavra, palavra, palavra dupla, flutuador de precisão única e flutuador de precisão dupla), a grande maioria das linguagens de programação permite o uso de código um número arbitrário de tipos de dados definidos pelo usuário. A JVM reconhece alguns tipos primitivos semelhantes aos de uma máquina típica, além de mais um tipo: a Promiscuous Object Reference. A linguagem Java também reconhece essas primitivas, e referências promíscuas a objetos. Embora uma variável possa ser restringida a não conter referências a nada que não seja uma classe específica, o idioma não faz distinções entre nenhum dos seguintes tipos de campos do tipo
List<String>
que podem ser mantidos pelaMyThing
classe de instânciaMyClass
:Uma referência a algo que o código sabe ser uma implementação imutável de
List<String>
Uma referência a uma instância de um tipo de lista mutável que nunca será exposta a nada que possa sofrer uma mutação.
Uma referência a uma lista mutável para a qual, exceto durante a execução dos
MyThings
métodos, nenhuma outra referência poderia existir em qualquer lugar do universo.Uma referência a uma lista mutável que pertence a outro objeto , que esse outro objeto gostaria
MyThing
de usar de alguma maneira.Uma referência a uma lista mutável que
MyThing
possui, mas que também foi exposta a alguns outros objetos para que eles possam fazer algo com ela.Embora todos esses campos possam ter tipo
List<String>
, eles possuem coisas muito diferentes. Uma linguagem expressiva pode permitir uma distinção entre esses significados, mas Java não. Como uma linguagem pode anexar significado a essas coisas (pelo menos fora de contextos genéricos) e executada na JVM, isso deixa muito espaço para as linguagens direcionadas à JVM expressar conceitos que Java não pode.fonte