← Stack web // stack web · back end · linguagem e plataforma

Java: compilar, rodar, responder

Java separa em dois momentos o que outras linguagens juntam num só. Primeiro o compilador lê o que você escreveu e recusa o que estiver errado. Depois a máquina virtual executa o resultado. Esse ciclo aparece já no primeiro arquivo e continua igual num sistema de dez anos.

O que o Java resolve

Código de servidor roda em máquina que você não escolheu, com sistema operacional que você não controla, e precisa continuar de pé anos depois de quem o escreveu ter saído do time. A resposta do Java foi pôr uma camada no meio do caminho: o compilador gera bytecode, um formato intermediário, e qualquer máquina virtual Java executa aquele mesmo arquivo, em Windows, Linux ou macOS.

A segunda dor é o erro que só aparece com o cliente na frente. Nome de método escrito errado, tipo trocado, argumento a mais: o compilador do Java para em todos esses casos e aponta o arquivo e a linha, antes de o programa subir. O preço disso é um passo a mais no caminho, e é esse passo que o hello world abaixo mostra na tela.

Os conceitos que você precisa antes da primeira linha

  • JDK, JVM e bytecode. A JVM é a máquina virtual que executa bytecode. O JDK é o kit que você instala pra desenvolver, e traz dentro a JVM mais o compilador. Instalando o JDK você fica com os dois comandos que interessam aqui, javac e java.
  • Classe e método main. Todo código Java mora dentro de uma classe. Pra que o programa tenha por onde começar, uma dessas classes precisa de um método com a assinatura public static void main(String[] args). É esse método que a JVM chama quando você manda executar.
  • O nome do arquivo casa com o nome da classe pública. Uma classe declarada como public class Ola tem que morar num arquivo chamado Ola.java, com a mesma caixa alta e baixa. Trocar isso faz o compilador reclamar antes de qualquer outra coisa.
  • Compilar e rodar são dois comandos. O javac lê o .java e escreve um .class. O java carrega esse .class e executa. Quem já usou linguagem interpretada estranha o passo do meio, e ele é o que dá ao compilador a chance de recusar seu código.
  • A biblioteca padrão já traz um servidor HTTP. O JDK inclui o módulo jdk.httpserver, com a classe com.sun.net.httpserver.HttpServer. Dá pra atender um pedido HTTP sem Maven, sem Gradle e sem framework, e é assim que o segundo programa desta página funciona.

A linguagem por dentro: tipos, classes e objetos

Java tem tipagem estática: toda variável declara o tipo, e o compilador recusa o programa se algum uso não bater. O erro que em linguagem dinâmica estoura com o sistema no ar, aqui morre no javac. Desde as versões modernas o var deixa o compilador inferir o tipo na declaração local, mas o tipo continua fixo.

  • Dois mundos de tipo: os primitivos (int, double, boolean, char), que são só o valor, e os objetos (String, List, qualquer classe sua). A caixa alta no nome denuncia o objeto.
  • Orientação a objetos não é opcional: todo código mora numa classe. Objeto nasce com new, o molde define atributos e métodos, herança usa extends e contrato usa interface. É a linguagem onde esses conceitos são o chão, não um recurso a mais.
  • Coleções com tipo dentro: List<String> é uma lista que só aceita texto. O par de sinais de menor e maior é o generics, o jeito de o compilador vigiar também o conteúdo das estruturas.
// tipos, classe e objeto em quinze linhas
import java.util.List;

public class Loja {
    public static void main(String[] args) {
        List<Double> precos = List.of(12.5, 30.0, 7.0);
        double total = 0;
        for (double p : precos) {       // for-each
            total += p;
        }
        Carrinho c = new Carrinho();    // objeto via new
        System.out.printf("R$ %.2f%n", total);
    }
}

class Carrinho {
    private int itens = 0;              // atributo encapsulado
    void add() { itens++; }             // método
}

É mais cerimônia que o hello world de outras linguagens, e é proposital: cada declaração é uma promessa que o compilador cobra.

Hello world: do javac ao endpoint

Tudo aqui acontece no terminal, em Linux, macOS ou Windows. Nenhuma IDE é obrigatória, e qualquer editor de texto serve pra criar os dois arquivos.

  1. Instale o JDK pela página oficial de download. A linha de suporte longo em vigor é o JDK 25, e o passo a passo abaixo roda igual nela e no JDK 21, a linha de suporte longo anterior. Feche e abra o terminal, e confira os dois comandos:

    java -version
    javac -version

    Os dois têm que responder com um número de versão. Se só o java responder e o javac disser que o comando não existe, o que entrou na máquina foi um runtime sem compilador. Volte e instale o JDK.

  2. Crie uma pasta pro exercício e entre nela:

    mkdir ola-java
    cd ola-java
  3. Crie o arquivo Ola.java, com exatamente este conteúdo:

    public class Ola {
        public static void main(String[] args) {
            System.out.println("Olá, mundo");
        }
    }

    O nome do arquivo tem que ser Ola.java, com O maiúsculo, porque a classe pública se chama Ola.

  4. Compile:

    javac Ola.java

    Sem -d na linha de comando, o compilador escreve o resultado na mesma pasta do fonte. Liste a pasta e você vê o arquivo novo:

    ls

    No Windows, o comando equivalente é dir.

  5. Execute, passando o nome da classe e sem a extensão:

    java Ola

    Escrever java Ola.class aqui dá erro. O comando espera o nome da classe, e a extensão faz parte do nome do arquivo.

  6. Agora o endpoint. Crie um segundo arquivo, Servidor.java, na mesma pasta:

    import com.sun.net.httpserver.HttpServer;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.nio.charset.StandardCharsets;
    
    public class Servidor {
    
        public static void main(String[] args) throws IOException {
            HttpServer servidor = HttpServer.create(new InetSocketAddress(8080), 0);
    
            servidor.createContext("/", troca -> responder(troca, "Olá, mundo"));
            servidor.createContext("/ping", troca -> responder(troca, "pong"));
    
            servidor.start();
            System.out.println("Servidor de pé em http://localhost:8080");
        }
    
        private static void responder(com.sun.net.httpserver.HttpExchange troca, String texto)
                throws IOException {
            byte[] corpo = texto.getBytes(StandardCharsets.UTF_8);
            troca.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
            troca.sendResponseHeaders(200, corpo.length);
            try (OutputStream saida = troca.getResponseBody()) {
                saida.write(corpo);
            }
        }
    }

    Nenhuma dessas classes veio de biblioteca externa. Todas moram dentro do JDK que você acabou de instalar.

  7. Compile e suba o servidor:

    javac Servidor.java
    java Servidor
  8. Com o servidor de pé, abra http://localhost:8080 no navegador. Pra conferir a outra rota sem sair do terminal, use uma segunda janela:

    curl http://localhost:8080/ping
  9. Pra encerrar, volte na janela do servidor e aperte Ctrl + C.

Um atalho que existe desde o Java 11

Depois de ver o ciclo dos dois comandos, dá pra usar a forma curta. O comando java Ola.java compila o fonte em memória e executa na sequência, sem escrever .class nenhum no disco. Vale pro rascunho e pro teste rápido. O ciclo com javac continua sendo o que acontece em qualquer projeto de verdade, e por isso ele vem primeiro aqui.

A prova de que funcionou. São três coisas, e cada uma prova uma etapa. Primeira: depois do javac Ola.java, o terminal não imprime nada e o ls mostra Ola.class ao lado do Ola.java. Esse arquivo novo é o bytecode, e a ausência de mensagem é o compilador dizendo que aprovou o código. Segunda: o java Ola imprime Olá, mundo numa linha e devolve o prompt na hora. Terceira: depois do java Servidor, o terminal mostra Servidor de pé em http://localhost:8080 e o cursor fica parado, sem voltar o prompt. Esse prompt travado é o sinal certo, porque o processo está de pé esperando pedido. Aí o navegador em http://localhost:8080 mostra Olá, mundo em texto cru, sem HTML em volta, e o curl devolve pong na segunda janela.

Quando dá errado, o erro tem endereço. O javac reclamando de class Ola is public, should be declared in a file named Ola.java aponta o nome do arquivo. Erro de conexão no navegador com a porta 8080 já ocupada por outro programa aparece como Address already in use no terminal, e o processo morre em vez de ficar esperando. Troque o número dentro do InetSocketAddress, recompile e rode de novo.

O que o Java não é

O mito mais teimoso é o parentesco com JavaScript. Os nomes se parecem por decisão comercial das empresas que lançaram cada um, e a semelhança para aí. Java compila antes de executar e cobra o tipo declarado. JavaScript nasceu pra rodar dentro do navegador, interpretado, com o tipo resolvido durante a execução. Código de um não roda no outro, e as bibliotecas de um não servem no outro. Se você quer o segundo, o caminho está em JavaScript.

A outra confusão aparece quando alguém diz que Java precisa de Spring, Maven e uma pilha de XML pra responder um pedido HTTP. O passo a passo acima não usou nada disso. O servidor saiu do próprio JDK e os comandos foram javac e java. Framework e ferramenta de build entram quando o projeto cresce, com dezenas de classes e dependências externas, e ficam de fora na primeira linha.

Fontes

  • dev.java, Getting Started, o portal oficial do Java, de onde saiu o ciclo de criar o fonte, compilar com javac e executar com java, e a nota de que desde o Java SE 11 os dois passos podem virar um. Conferida em 15/08/2026.
  • Manual do javac, JDK 25, onde está a regra de que sem a opção -d cada arquivo .class vai parar na mesma pasta do fonte que o gerou. Conferida em 15/08/2026.
  • Manual do java, JDK 25, com a forma java arquivo.java do modo de arquivo-fonte e a descrição das opções de versão. Conferida em 15/08/2026.
  • API de HttpServer, módulo jdk.httpserver, de onde vieram as assinaturas de create, createContext e start usadas no programa. Conferida em 15/08/2026.
  • API de HttpExchange, que documenta sendResponseHeaders e o significado do segundo argumento, o tamanho exato do corpo em bytes. Conferida em 15/08/2026.
  • Página oficial de download do Java, por onde se baixa o JDK. Conferida em 15/08/2026.

Rodamos esse hello world na nossa máquina em 15/08/2026, no Temurin OpenJDK 21.0.12 LTS em Linux. O javac Ola.java não imprimiu nada e deixou o Ola.class na pasta, o java Ola respondeu Olá, mundo, e o java Servidor imprimiu a linha do servidor de pé. O curl na rota raiz devolveu HTTP/1.1 200 OK com o corpo Olá, mundo, e na rota /ping devolveu HTTP/1.1 200 OK com o corpo pong. A porta 8080 estava ocupada por outro programa nessa máquina, o terminal mostrou Address already in use igual ao descrito acima, e o servidor subiu depois de trocar o número dentro do InetSocketAddress.

Para continuar

Do lado do back end, a linguagem é escolha. C# segue o mesmo caminho de compilar antes de rodar, com outra sintaxe e uma linha de comando que junta build e execução num passo só. Ruby vai pelo lado oposto, sem compilação separada, e mostra o quanto essa decisão muda o dia a dia. As três estão lado a lado no mapa da stack web, junto do banco de dados e das APIs que vêm depois.

O curso desta trilha está em preparação. A lista paga menos.

Os tutoriais daqui continuam gratuitos. O que está a caminho é um curso pago que transforma esse mapa em formação guiada, na ordem certa e com projeto. Deixe seu e-mail: você recebe os estudos novos gratuitos e, no lançamento, o desconto de quem entrou na lista primeiro.