Java sem Spring + GraalVM, o Resultado foi impressionante 22/09/2026 # Java sem Spring + GraalVM, o Resultado foi impressionante.  ## Motivação Assistindo vídeos de gringos onde alguns estão no movimento de que menos é mais, decidi fazer algo semelhante. Ao invés de gastar recursos computacionais com um Framework como o Spring, mesmo que a produtividade seja extremamente superior, eu decidi fazer algo o mais enxuto possível, e durante este blogpost vamos discorrer sobre as vantagens e desvantagens.  ## Desafios Tive alguns desafios, pois como eu não tenho dinheiro para ter acesso as melhores IA's como por exemplo ao Codex e Claude, usei o bom e velho Gemini Gratuito para me ajudar no Backend, e o Gepeto para me ajudar a estilizar o frontend. Dentro dos desafios tive: 1. Configurar o HttpServer na mão 1. Segurança 1. Persistências dos dados manual 1. Falta da Injeção de dependências ## Vantagens Não obstante, não só de coisa ruim é usar o Java sem Framework's, tive muitos benefícios, como: 1. Performance 1. Gasto de RAM baixo 1. Controle Total 1. Entendimento do porquê os Framework's implementam as coisas como são 1. Inicialização instantânea ## Como foi fazer o projeto? Eu escolhi refazer meu Blog, que já estava funcionando, mas estava gastando 300~400 mb de ram sem fazer absolutamente nada, apenas para existir. Fazendo as contas, eu tive pelo menos 10x gasto de ram só por não usar o Framework. Além da compilação com GraalVM que otimiza o teu código especificamente pro processador onde irá rodar. Agora, não ter injeção de dependência, configurar o HttpServer na unha realmente foi bem complicado. Vou abrir um adendo aqui, este projeto é pessoal, então compensa muito abrir mão de legibilidade e manutenção para ter algo mais performático, isso não se aplica a empresas que precisam manter bases de código complexas, isso é totalmente inviável. Agora para códigos que só você e seus amigos vão utilizar, é mais do que necessário economizar recursos. Uma VPS na data que escrevi este post custa R$25 para vir apenas com 1 Giga de Ram e 1 CPU. E eu ainda fui mais ousado nesse projeto, eu descartei o JS do frontend e usei o HTMX(eu sei que HTMX é JS, mas eu não usei tanto JS próprio a não ser para o carrosel), e ainda descartei um servidor para banco de dados, simplesmente usei o SQLite que deu conta do recado sorrindo, pois a natureza do site é ter praticamente só leitura, e como o SQLite é um arquivo que roda no mesmo lugar do binário do GraalVM, é praticamente instantânea a leitura. Como eu não tinha Thymeleaf, eu tive que inventar uma sintaxe própria para processar os HTML's com o conteúdo dinâmico. Esta arquitetura enxuta e arcáica resolveu meu problema, talvez algumas pessoas se preocupem com escala sem realmente ter a necessidade, seria esse o mal de todo pleno?  ## Conclusão Antes de concluirmos quero destacar a atrocidade que ficou meu Main.java, algo que seria inimaginável no Spring: ```java package top.leonam; import com.sun.net.httpserver.HttpServer; import top.leonam.bd.CategoriaImpl; import top.leonam.bd.Database; import top.leonam.bd.PostImpl; import top.leonam.bd.TagImpl; import top.leonam.controller.*; import top.leonam.service.*; import java.io.IOException; import java.net.InetSocketAddress; import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; public class Main { static Logger logger = Logger.getLogger("MAIN"); public static int PORTA_PADRAO = 7979; public static int BACKLOG_PADRAO = 1024; static void main(String[] args) throws IOException { System.setProperty("sun.net.httpserver.nodelay", "true"); System.setProperty("sun.net.httpserver.maxReqTime", "15"); System.setProperty("sun.net.httpserver.maxRspTime", "15"); Database.inicializarBanco(); var postRepository = new PostImpl(); var categoriaRepository = new CategoriaImpl(); var tagRepository = new TagImpl(); var postListService = new PostListService(); var arquivoService = new ArquivoService(); var indexService = new IndexService(postRepository, categoriaRepository, tagRepository); var postService = new PostService(postRepository); var categoriaService = new CategoriaService(categoriaRepository, postRepository, postListService); var tagService = new TagService(tagRepository, postRepository, postListService); var indexController = new IndexController(indexService); var arquivoController = new ArquivoController(arquivoService); var postController = new PostController(postService); var categoriaController = new CategoriaController(categoriaService); var tagController = new TagController(tagService); var staticController = new StaticController(); var postPaginationService = new PostPaginationService(postRepository); var postPaginationController = new PostPaginationController(postPaginationService); var sitemapController = new SitemapController(postRepository); var servidor = HttpServer.create(new InetSocketAddress(PORTA_PADRAO),BACKLOG_PADRAO); servidor.createContext("/blog/", postController); servidor.createContext("/posts", postPaginationController); servidor.createContext("/categoria/", categoriaController); servidor.createContext("/tag/", tagController); servidor.createContext("/css/", staticController); servidor.createContext("/js/", staticController); servidor.createContext("/img/", staticController); servidor.createContext("/arquivos", arquivoController); servidor.createContext("/sitemap.xml", sitemapController); servidor.createContext("/", indexController); servidor.setExecutor(Executors.newVirtualThreadPerTaskExecutor()); servidor.start(); logger.log(Level.INFO, "Servidor rodando na porta " + PORTA_PADRAO); System.gc(); } } ``` É bonito? Não, mas resolve meu problema. No fim das contas, a engenharia de software é a arte de gerenciar trade-offs. Trocar a produtividade e a robustez do Spring por 300 MB de economia de RAM não faz sentido para um e-commerce corporativo, mas para um projeto pessoal onde o custo e a performance bruta mandam, a jornada de voltar às raízes do Java foi extremamente gratificante.