Oiê! Vou contar para vocês agora, pouco sobre linguagens interpretadas versus linguagens compiladas, ou interpretadores e compiladores. As linguagens de programação surgiram já junto com os primeiros computadores. Os primeiros computadores eletrônicos surgiram meados da década de 1940 e naquela época para conseguir programar eles, os programadores tinha que entrar uma longa sequência de zeros e uns, que eram os programas linguagem de máquina, porque o hardware do computador no final das contas a única coisa que ele entende são zeros e uns. Mas imagina como era difícil a vida dos programadores ficando digitando ali zeros e uns o tempo todo. Fora que o teclado com duas teclas não funcionava muito bem, né? Então o que é que eles acabaram desenvolvendo? Depois de alguns anos, 1948, apareceu a linguagem de montagem, ou assembly language, inglês. Que eram comandos bem curtinhos, por exemplo esse aqui que a gente vê, ADD AX, BX, que nesse caso era comando de adicionar, de soma, de dois registradores, onde registradores são pedacinhos ali da memória que fica dentro do processador e que tem acesso muito rápido. Então eram comandos muito simples, desse tipo, de poucas letras, não é? Mas fazer programas nessas linguagens de montagem era muito difícil. Para fazer programas simples você precisava de centenas desses comandos aqui sequência, entender e desenvolver software apenas com essa linguagem era muito difícil. Então apareceu a ideia de se criar linguagens de programação, linguagens de programação mais próximas da nossa fala, da linguagem natural dos seres humanos, usando palavras língua inglesa por exemplo e usando fórmulas matemáticas próximas do que os matemáticos já utilizavam. A primeira linguagem alto nível que apareceu foi a linguagem FORTRAN. FORTRAN significa formula translator. A ideia era traduzir fórmulas da matemática para a linguagem de máquina do computador. Ela nasceu 1957. Logo depois nasceu uma linguagem bem interessante que se chama LISP, que a ideia era fazer manipulação de listas, de símbolos foi usada inicialmente para inteligência artificial, foi criada lá no MIT. Essas linguagens, elas utilizavam formas diferentes de se executar. O FORTRAN era uma linguagem compilada e o LISP era linguagem interpretada, que daqui a pouco já explico melhor o que é isso. Depois foram aparecendo várias outras linguagens de alto nível cada vez aumentando esse nível de abstração dessas linguagens. Então a orientação a objetos surgiu 67 com o Simula e depois foi aperfeiçoada até chegar no ponto que a gente conhece hoje com o Smalltalk-80. Depois apareceram outras linguagens, toda aquela família das linguagens C, C++, Objetive C e hoje dia a gente tem uma série de opções, Java, Python, Ruby e monte de outras linguagens aí modernas que têm aparecido nos últimos anos. Agora, então como funcionam primeiro as linguagens interpretadas como era LISP quando surgiu. A ideia é o seguinte: você escrevia o código fonte do seu programa na linguagem LISP num arquivo texto, que a gente chama de o arquivo do código fonte. Daí esse código fonte, esse arquivo texto, é dado como entrada para programa que se chama interpretador. O que é que esse programa interpretador faz? Ele lê uma linha por vez, desse arquivo de entrada, do seu código fonte, e daí ele interpreta aquela linha. Ou seja, o que é que é? O interpretador é programa, programa executável, que está rodando no computador, que ele lê aquela linha e daí ele traduz aquela linha para linguagem de máquina do computador e executa. E ele vai linha por linha executando esse programa. Então à medida que ele vai lendo o arquivo de entrada ele vai interpretando e executando, onde executar significa na verdade transformar para o código binário e executar usando as instruções do processador do hardware do computador. Ao fazer isso, o programa vai gerando uma saída, ele imprime alguma coisa na tela, ou imprime numa impressora, ou hoje dia talvez envia esses dados pela internet, ou gera uma imagem ou gera som, algum tipo de saída o programa gera. Então estas aqui são as linguagens interpretadas que funcionam baseadas num interpretador. Depois a gente tem as linguagens como o FORTRAN ou como o C, que são linguagens compiladas. Como é que funcionam? A gente tem de novo o código fonte que é aquele arquivo com o nosso programa, o arquivo texto, puro com o nosso programa e a gente dá esse código fonte de entrada para compilador. Compilador é programa. Que é que ele faz? Ele traduz aquele código fonte numa linguagem de programação de alto nível para linguagem de máquina que aqui a gente está chamando de código objeto e ele grava num outro arquivo, que é esse arquivo objeto, onde vai ter lá dentro os comandos linguagem de máquina a serem executados. E daí, depois mais tarde, quando a gente quiser executar esse programa, a gente executa o código objeto e daí precisa de programa para executar. Normalmente é o próximo sistema operacional, que a gente usa no nosso computador, que é esse executor de programas código objeto. Então a gente fala para o sistema operacional "Execute tal programa" ou pode ser digitando normalmente o programa num terminal ou se tiver uma interface gráfica fazendo duplo clique lá no ícone do programa a gente fala para o sistema operacional "Execute esse programa" e daí sim ele vai pegar esses códigos já linguagem máquina e executar e daí gera a saída. Então essas aqui são as linguagens compiladas. Posteriormente apareceram linguagens híbridas que são linguagens compiladas e interpretadas ao mesmo tempo. Como é que isso funciona? E na verdade Smalltak, Java e Python são exemplos dessas linguagens híbridas. Funciona assim: a gente escreve o nosso programa, no código fonte, grava num arquivo texto. Por exemplo se for programa Java a gente vai gravar num arquivo .java, que é arquivo texto normal e daí antes de iniciar a execução do programa a gente usa compilador, Java tem o JavaC, que é o compilador que vem junto lá com a linguagem Java, dedicado à linguagem Java e esse compilador, o JavaC no caso do Java, traduz o código fonte Java para bytecode. O que é que é bytecode? É uma linguagem específica que os criadores do Java definiram que é parecido com uma linguagem de montagem, parecido com assembly, que é aqueles ADD AX, BX, só que é uma linguagem pouquinho diferente e esse novo programa nesse bytecode é gravado num arquivo. Esse arquivo Java se chama .class, tá? Você vai gravar, vai criar vários .java, você vai compilar ele e ele vai gerar esses vários .class. E daí sim, quando a gente quiser executar esse programa a gente vai usar interpretador de Java, que no caso do Java é uma máquina virtual de Java, que daqui a pouco a gente fala disso, que vai ler esses bytecodes, então, por exemplo no terminal do Java espaço e o nome do meu arquivo .class, que daí ele vai executar ler esses bytecodes e começar a executar, onde executar nesse caso é para cada bytecode que ele lê, ele converte aquilo para linguagem máquina e executa o programa ali no hardware específico. Então tem esses 2 passos. E Java fez isso, a gente vai ver porque é que Java fez dessa forma. A filosofia de Java, quando Java apareceu por volta de 1995, nasceu com a seguinte ideia: o slogan do Java é "write once, run everywhere". O que é que significa isso? Antigamente quando você tinha programa que rodava num computador, num PC e depois você queria rodar num Mac por exemplo, ou queria rodar num computador com UNIX, você tinha que recompilar toda a vez o programa. Porque o mesmo programa não funcionava dois sistemas operacionais diferentes. E a ideia do Java era que eles queriam escrever único programa que funcionasse identicamente, que vocês escreve o programa, compila e daí o mesmo programa roda de forma idêntica qualquer sistema operacional, Mac, iOS, Linux, UNIX, ou até num celular com Android, ou num celular com iOS, a ideia era que rodasse qualquer lugar, essa foi a filosofia da linguagem Java. Além disso diferentes tipos de computadores. Então o mesmo programa rodar tanto num notebook, quanto num desktop, quanto num celular, quanto num relógio que o mesmo programa pudesse rodar diferentes lugares. Daí para que essa ideia fosse implementada, aliás outra coisa, Java nasceu 95 que foi o ano que a internet se popularizou e a Web se popularizou no Mundo inteiro, porque até então a internet ela era muito mais restrita ao mundo acadêmico. 95 empresas e pessoas normais aí do mundo real começaram a usar a internet amplamente e o Java nasceu com essa ideia de ser uma linguagem para a internet, onde você pode baixar programas da internet, rodar no seu computador, de uma forma até transparente, você vai num site e já começa a rodar programa que você nem sabia que existia e automaticamente, por ser Java, já estava rodando. Para que isso funcionasse, para que você não precisasse de ficar recompilando dezenas de vezes para diferentes computadores, diferentes sistemas operacionais, como que eles fizeram isso? Eles pegaram uma ideia que Smalltalk já tinha exercitado lá 1980: criar uma máquina virtual. Ou seja, quando a gente escreve programa para Java, vez de escrever para uma máquina Para uma máquina específica, por exemplo, para o meu computador aqui, a gente escreve para uma máquina virtual, que é a máquina virtual Java, que é uma máquina ideal, que tem uma certa linguagem, que na verdade é o bytecode de Java e tem uma certa lista de funções que são bibliotecas de funções que ela já sabe executar, tem uma fórmula padrão de fazer entrada de dados, saída de dados, e escrevendo programa para essa máquina virtual Java, qualquer sistema operacional, qualquer tipo de computador que tenha uma máquina virtual Java ia conseguir executar exatamente o mesmo programa. Por isso que é right ones, você escreve o programa uma única vez e ele roda qualquer lugar. Agora, como que é essa tal de máquina virtual Java? A gente fala muito JVM, que é a sigla de Java Virtual Machine, inglês. Vamos ver como é que funciona. Aqui do lado esquerdo primeiro, a gente tem os nossos arquivos fonte Java, arquivos .java e daí a gente passa pelo compilador Java C, que vai gerar os arquivos .class. Se você está usando o ambiente de tipo Eclipse, o JavaC já está imbutido. O Eclipse, quando você salva o arquivo .java, automaticamente, ele já compila e já gera o .class, imediatamente. A gente não precisa na mão rodar esse Javac. Mas se você está desenvolvendo num editor de textos puro e está trabalhando pelo terminal, você precisa chamar explicitamente JavaC. Ele vai gerar esses vários arquivos .class, que tem aquele bytecode lá dentro, se quiser você pode juntar vários .class num arquivo, num "Archive", que é .jar, é Java Archive, você vai ter monte de arquivos dentro de único .jar, isso é opcional, e você vai mandar executar cima de uma JVM. Essa parte amarela aqui é a JVM, a JVM é específica para determinado hardware. Se você tem uma JVM do Windows para PC, é diferente da JVM do Linux, que é diferente da JVM do Macintosh, que é diferente de uma JVM que vai rodar no seu telefone celular, mas existem JVM's hoje dia para todos esses principais sistemas operacionais e hardwares. Aqui tem uma JVM, no meu notebook tem uma JVM, tem até JVM para relógio, A JVM é específica para cada desses sistemas, mas cima da JVM, aí é código único. Aqui tem exemplo de uma JVM para processador Intel, que roda num PC e aqui baixo tem esse PC, que pode ser Windows ou Linux ou macOS e aqui tem exemplo de telefone celular, que tem sistema operacional que pode ser o Android, por exemplo, e você vai ter todas as bibliotecas Java aqui e nessa parte amarela você tem a JVM si, que vai ter o verificador de bytecode, para ver se o bytecode está no formato correto. Depois vai haver interpretador que vai conseguir interpretar os comandos e pode ter algumas otimizações aqui, as otimizações são feitas por essa parte chamada JIT compiler e tem todo o gerenciamento de memória, que quando você cria novos objetos ele aloca a memória. Ou quando você não precisa mais dos objetos, ele joga no lixo. Essa é a parte que se chama garbage collection. E tem essa ideia de que você escreve esse programa Java e ele pode rodar qualquer JVM. Essa figura mostra exemplo, também, que hoje dia tem outras linguagens que você pode rodar, executar, numa JVM, não só Java. JVM nasceu para o Java, mas depois outras linguagens começaram a aproveitar a JVM, porque é sistema muito robusto, muito eficiente. Por exemplo, se você escreve programa Python, tem compilador Python que se chama Jython, que, na verdade, ele gera bytecode Java, que roda na JVM. Se você tem programa Python e compila com Jython, esse seu programa agora pode rodar qualquer JVM, qualquer sistema operacional, qualquer computador que executa a JVM. Esse é o poder da JVM. Quando você está trabalhando com Java, você não precisa ficar se preocupando com os detalhes, mas quando você faz sistemas mais complexos ou quer fazer alguma coisa mais sofisticada, às vezes a gente precisa olhar para essa parte aqui mais de baixo. Particular, você não programar bytecode na mão, quase nunca a gente vai escrever bytecode na mão, que é aquela linguagem de montagem de Assembly de Java, a gente vai gerar o bytecode automaticamente a partir do código Java que a gente escreve. Tem algumas coisas muito avançadas que, por exemplo, o Eclipse faz isso, porque o Eclipse si é software muito avançado, que ele tem que manipular o próprio código de Java, daí como ele faz? Tem umas bibliotecas que são manipuladores de bytecode, então, talvez algum dia, depois que você avance bastante e se torne programador bem experiente, que vai fazer algum projeto muito avançado, talvez você vá ter que mexer no bytecode, mas tem classes Java, que são manipuladores de bytecode que nos ajudam a escrever bytecode. No fim, provavelmente você nunca vai programar bytecode si. Resumindo, as linguagens podem ser compiladas, elas podem ser interpretadas, mas hoje dia a gente tem essas linguagens compiladas, interpretadas e boa parte das linguagens mais recentes, desenvolvidas nos últimos anos, têm esse passo de compilação inicial e depois são interpretadas por uma máquina virtual. Está bom? Então, por hoje era isso.