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,
javacejava. - 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 Olatem que morar num arquivo chamadoOla.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
javaclê o.javae escreve um.class. Ojavacarrega esse.classe 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 classecom.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 usaextendse contrato usainterface. É 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.
-
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 -versionOs dois têm que responder com um número de versão. Se só o
javaresponder e ojavacdisser que o comando não existe, o que entrou na máquina foi um runtime sem compilador. Volte e instale o JDK. -
Crie uma pasta pro exercício e entre nela:
mkdir ola-java cd ola-java -
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 chamaOla. -
Compile:
javac Ola.javaSem
-dna linha de comando, o compilador escreve o resultado na mesma pasta do fonte. Liste a pasta e você vê o arquivo novo:lsNo Windows, o comando equivalente é
dir. -
Execute, passando o nome da classe e sem a extensão:
java OlaEscrever
java Ola.classaqui dá erro. O comando espera o nome da classe, e a extensão faz parte do nome do arquivo. -
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.
-
Compile e suba o servidor:
javac Servidor.java java Servidor -
Com o servidor de pé, abra
http://localhost:8080no navegador. Pra conferir a outra rota sem sair do terminal, use uma segunda janela:curl http://localhost:8080/ping -
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
javace executar comjava, 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-dcada arquivo.classvai parar na mesma pasta do fonte que o gerou. Conferida em 15/08/2026. - Manual do
java, JDK 25, com a formajava arquivo.javado modo de arquivo-fonte e a descrição das opções de versão. Conferida em 15/08/2026. - API de
HttpServer, módulojdk.httpserver, de onde vieram as assinaturas decreate,createContextestartusadas no programa. Conferida em 15/08/2026. - API de
HttpExchange, que documentasendResponseHeaderse 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.