🚨 Why your 4GB JVM app still gets OOMKilled (even when heap looks fine) Most developers assume: JVM memory = Heap But that’s only part of the story. Let’s look at a common real-world setup: You configure: -Xmx=4g Container memory limit = 4GB Looks perfect, right? ❌ Not really. Your JVM uses much more than just heap. Here’s where the “hidden” memory goes: 🔹 Metaspace Stores class metadata (Spring, Hibernate, proxies) ~150–250MB (no strict cap by default) 🔹 Thread Stacks Each thread ≈ 1MB 200 threads = ~200MB (Tomcat + HikariCP + Kafka + @Async) 🔹 Direct Buffers (Off-Heap) Used by WebClient, Kafka, Netty - Not visible in heap, not GC-managed 🔹 Code Cache JIT compiled code ~50–150MB (grows as app warms up) 🔹 GC Overhead Garbage collector needs working memory too 💥 Reality Check 4GB heap + 200MB metaspace + 200MB threads + 100MB buffers + 100MB code cache 👉 Total ≈ 4.7GB But your container limit is still 4GB. Result? 🚫 Kubernetes OOMKills your pod And the confusing part: ✔️ Heap looks fine (~2.5GB used) ❌ But your app still crashes Because OOMKill is based on total process memory, not just heap. ✅ The Fix ✔️ Keep heap at 70–75% of container memory ✔️ If container = 4GB → set -Xmx=3g ✔️ If -Xmx=4g → container ≥ 5.2GB ✔️ Cap metaspace: -XX:MaxMetaspaceSize=256m ✔️ Cap direct memory: -XX:MaxDirectMemorySize=256m ✔️ Monitor non-heap usage: /actuator/metrics/jvm.memory.used 💡 Takeaway If you're only monitoring heap, you're missing the full picture. 👉 Always consider total JVM memory footprint in containerized environments. #Java #JVM #SpringBoot #Kubernetes #Microservices #DevOps #Performance #BackendEngineering #SoftwareEngineering #Programming
OOMKilled by JVM Memory: Beyond Heap
More Relevant Posts
-
🚀 Day 18 — Memory Optimization Strategies Every Java Developer Should Know ~ Poor memory management doesn’t just slow applications — it kills microservices at scale. Here are the core strategies architects use to keep JVM apps fast, stable, and OOM-free 👇 🔹 1. Prefer Bounded Caches (Never Use Unbounded Maps!) Unbounded caches = slow memory death. Use TTL + max-size. Tools: Caffeine, Redis, Guava Cache. 🔹 2. Reduce Object Creation (Avoid GC Pressure) Frequent allocations → GC churn → latency spikes. Use: ✔ Object pooling (selectively) ✔ Reuse buffers ✔ Prefer primitives over wrappers 🔹 3. Tune JVM Heap the Right Way Don’t set memory blindly. Follow this rule: 🧠 “Enough for burst traffic, small enough for fast GC.” Use: -Xms, -Xmx, -XX:+UseG1GC 🔹 4. Avoid Large Objects in Memory 100MB+ arrays, huge DTOs, or large JSON blobs lead to promotion failures. Stream data instead of loading it whole. Use reactive I/O where needed. 🔹 5. Use Efficient Data Structures Right structure = half memory. Examples: • ArrayList instead of LinkedList • EnumSet instead of Set<Enum> • IntStream instead of Stream<Integer> 🔹 6. Profile & Watch for Leaks Use continuous monitoring: 📌 Prometheus + Grafana 📌 Heap dump analysis (MAT / VisualVM) 📌 Look for steadily increasing heap usage 🔹 7. Reduce Retained References Common pitfalls: • Static maps holding data • ThreadLocal misuse • Listeners not removed • Singletons storing heavy objects 🔹 8. Optimize Serialization JSON is expensive. Use: ⚡ Jackson Afterburner ⚡ Protocol Buffers for high-throughput services 🔹 9. Prefer External Queues Over In-Memory Buffers Kafka / RabbitMQ > internal BlockingQueue for large workloads. 🎯 In short: Fast systems are engineered — not accidental. Memory optimization is a continuous discipline, not a one-time fix. What are different memory optimization techniques you have used in your work? #Microservices #Java #100DaysofJavaArchitecture #MemoryManagement #JVM
To view or add a comment, sign in
-
-
🚀 Understanding JVM Memory Areas + JVM Tuning in Kubernetes - Best Practices If you’re working with Java in production, especially inside Kubernetes containers, understanding JVM memory internals is non‑negotiable. 🧠 JVM Memory is broadly divided into: Heap (Young & Old Generation) Metaspace Thread Stacks Program Counter (PC) Register Native Memory (Direct Buffers, JNI, GC, etc.) 💡 Why this matters in Kubernetes? Because containers have memory limits, and the JVM does not automatically understand them unless configured properly. Wrong tuning = OOMKilled pods, GC storms, or wasted resources. ✅ JVM Tuning Best Practices for Kubernetes 1. Always Make JVM Container-Aware Modern JVMs (Java 11+) support containers, but be explicit: -XX:+UseContainerSupport 2. Size Heap Based on Container Memory -XX:MaxRAMPercentage=70 -XX:InitialRAMPercentage=50 3. Leave Headroom for Non-Heap Memory JVM uses memory beyond heap: Metaspace Thread stacks Direct buffers GC native memory Recomendation : Heap ≤ 70–75% of container memory 4. Use the Right Garbage Collector For most Kubernetes workloads: -XX:+UseG1GC 5. Tune Metaspace Explicitly -XX:MaxMetaspaceSize=256m 6. Each thread consumes stack memory. -Xss256k 7. Watch Out for OOMKilled vs Java OOM Java OOM → Heap or Metaspace issue OOMKilled → Container exceeded memory limit Found this helpful? Follow Tejsingh K. for more insights on Software Design, building scalable E-commerce applications, and mastering AWS. Let’s build better systems together! 🚀 #Java #JVM #Kubernetes #CloudNative #PerformanceEngineering #DevOps #Backend #Microservices
To view or add a comment, sign in
-
-:Improving API Performance in Spring Boot :- Optimizing APIs in Spring Boot is crucial for building scalable and high-performance backend systems. Here are some practical techniques that made a real difference in my projects: ✔ Use Caching (@Cacheable) Reduce repeated DB calls using Spring Cache with Redis/EhCache. ➡️ @Cacheable, @CacheEvict can significantly cut response time. ✔ Optimize Database Access (JPA/Hibernate) • Use proper indexes • Avoid N+1 queries • Use DTO projections instead of fetching full entities ✔ Connection Pooling (HikariCP) • Spring Boot uses HikariCP by default — tune pool size for better throughput. ✔ Pagination Instead of Large Responses Use Pageable to limit data returned per request. ✔ Lazy Loading & Fetch Strategies Avoid unnecessary data fetching using FetchType.LAZY. ✔ Actuator + Monitoring Track performance using Spring Boot Actuator ✔ API Rate Limiting Use tools like Bucket4j to prevent overload. What’s your technique for improving Spring Boot performance? comment here 👇 #SpringBoot #Java #Backend #API #Performance #Microservices #Hibernate #Coding #Tech
To view or add a comment, sign in
-
🚀 Day 16 – ClassLoaders: Architecture View If JVM is the engine, ClassLoaders are the gatekeepers — responsible for loading every .class into memory exactly when needed. Understanding ClassLoader architecture helps you debug class-not-found issues, memory leaks, shading conflicts, and container-based classpath problems. 🔍 How Class Loading Works JVM uses a hierarchical delegation model: 1️⃣ Bootstrap ClassLoader Loads core Java classes (java.*) Part of the JVM (native) 2️⃣ Extension / Platform ClassLoader Loads classes from $JAVA_HOME/lib/ext or platform modules 3️⃣ Application / System ClassLoader Loads everything from your classpath or app’s JARs ➡️Custom ClassLoaders Used by app servers, frameworks, plugin systems (Tomcat, OSGi, Spring Boot Layers) 🧠 Key Architecture Concepts ✔ Parent Delegation Model Child → Parent first. Prevents overriding core Java classes (security). ✔ Shadowing / Overriding Custom loaders can break delegation intentionally (OSGi, plugin engines). ✔ Namespace Isolation Each ClassLoader has its own namespace — Same class name loaded by two loaders = treated as different classes. ✔ Hot Reloading & Dynamic Loading Custom loaders allow: - Reloading modules - Loading JARs at runtime - Containerized class isolation 🎯 Why Should Developers/Architect Know This? - Fixing ClassNotFoundException, NoClassDefFoundError, LinkageError - Designing microservice modular architecture - Understanding how frameworks like Spring Boot, Quarkus, Tomcat, Jetty,Hadoop manage classes - Optimizing startup time (JVM warmup, classpath scanning) #Java #Microservices #ClassLoaders #JVM #100DaysofJavaArchitecture
To view or add a comment, sign in
-
-
Things nobody tells you about Java Spring Boot - Until you’re in production After working on enterprise-scale applications handling 75,000+ daily transactions for a Fortune 5 client, here are my biggest takeaways: ✅ Design for failure — Always implement circuit breakers (Resilience4j). Production will surprise you. ✅ Kafka is a game changer — Async event-driven architecture saved us during peak load spikes. ✅ Database tuning matters more than code — SQL query optimization saves more performance than any code refactor. ✅ Don’t ignore logging — Structured logs with correlation IDs across microservices saved hours of debugging. ✅ Test early, test often — JUnit, Mockito and BDD approach caught bugs before they reached production. ✅ API contracts — Poor REST API design causes more problems than bad code. #Java #SpringBoot #Microservices #BackendDevelopment #SoftwareEngineering #TechCommunity #JavaDeveloper
To view or add a comment, sign in
-
🚨 𝗬𝗼𝘂𝗿 𝗦𝗽𝗿𝗶𝗻𝗴 𝗕𝗼𝗼𝘁 𝗔𝗽𝗽 𝗜𝘀 𝗤𝘂𝗶𝗲𝘁𝗹𝘆 𝗕𝘂𝗿𝗻𝗶𝗻𝗴 𝗤𝘂𝗲𝗿𝗶𝗲𝘀 🤯 Most developers use @𝗙𝗼𝗿𝗺𝘂𝗹𝗮 and @𝗘𝗻𝘁𝗶𝘁𝘆𝗚𝗿𝗮𝗽𝗵 interchangeably. That one mistake can turn a 1-query operation into 1,001. 𝗪𝗵𝗮𝘁'𝘀 𝗮𝗰𝘁𝘂𝗮𝗹𝗹𝘆 𝗵𝗮𝗽𝗽𝗲𝗻𝗶𝗻𝗴 𝘂𝗻𝗱𝗲𝗿 𝘁𝗵𝗲 𝗵𝗼𝗼𝗱? @Formula looks innocent: @𝙁𝙤𝙧𝙢𝙪𝙡𝙖("(𝙎𝙀𝙇𝙀𝘾𝙏 𝘾𝙊𝙐𝙉𝙏(*) 𝙁𝙍𝙊𝙈 𝙤𝙧𝙙𝙚𝙧𝙨 𝙤 𝙒𝙃𝙀𝙍𝙀 𝙤.𝙘𝙪𝙨𝙩𝙤𝙢𝙚𝙧_𝙞𝙙 = 𝙞𝙙)") 𝙥𝙧𝙞𝙫𝙖𝙩𝙚 𝙇𝙤𝙣𝙜 𝙤𝙧𝙙𝙚𝙧𝘾𝙤𝙪𝙣𝙩; But Hibernate fires a separate subquery for every row fetched. 500 customers → 500 extra DB hits. That's the 𝗡+𝟭 problem wearing a clean disguise. @𝗘𝗻𝘁𝗶𝘁𝘆𝗚𝗿𝗮𝗽𝗵 𝗱𝗼𝗲𝘀 𝗶𝘁 𝗿𝗶𝗴𝗵𝘁: @𝙀𝙣𝙩𝙞𝙩𝙮𝙂𝙧𝙖𝙥𝙝(𝙖𝙩𝙩𝙧𝙞𝙗𝙪𝙩𝙚𝙋𝙖𝙩𝙝𝙨 = {"𝙤𝙧𝙙𝙚𝙧𝙨", "𝙖𝙙𝙙𝙧𝙚𝙨𝙨"}) 𝙇𝙞𝙨𝙩<𝘾𝙪𝙨𝙩𝙤𝙢𝙚𝙧> 𝙛𝙞𝙣𝙙𝘼𝙡𝙡𝙒𝙞𝙩𝙝𝙊𝙧𝙙𝙚𝙧𝙨(); One JOIN. All related data. Done. The real-world gap Same 500 products, with category + supplier associations: ❌ Wrong fetch strategy → 1,001 queries ✅ @EntityGraph → 1 query Same data. P99 latency going from 80ms to 4 seconds. In production. 𝗪𝗵𝗲𝗻 𝘁𝗼 𝘂𝘀𝗲 𝘄𝗵𝗶𝗰𝗵 • ScenarioUseComputed value (count, sum) ->@Formula • Fetching related entities -> @EntityGraph • Sort/filter by derived column -> @Formula • Avoiding lazy loading on APIs -> @EntityGraph One question cuts through the confusion every time: "Am I computing something, or loading something?" They're not competing tools — they solve different problems. The mistake is reaching for @𝗙𝗼𝗿𝗺𝘂𝗹𝗮 where a JOIN belongs. Most Spring Boot performance issues I've seen weren't bad logic. They were the wrong fetch strategy in the right place. Have you hit this in production? Drop it in the comments 👇 #Java #SpringBoot #Programming #SoftwareEngineering #SoftwareDevelopment #JPA #Hibernate #BackendDevelopment #BackendEngineering #APIDesign #SystemDesign #PerformanceOptimization #CleanCode #CodeQuality #TechDebt #TechCommunity #100DaysOfCode #LearnToCode #Developer #CodingLife
To view or add a comment, sign in
-
-
I built an order management system using Java, Spring Boot, and Apache Kafka!🚀 Motivated by deepening knowledge in Kafka, my goal was to simulate an asynchronous order lifecycle, from placement to delivery, using event-driven architecture. This project taught me how powerful it is to combine clean design patterns with asynchronous messaging. The system becomes much easier to extend, test, and analyze. GitHub: Project: https://lnkd.in/dp4CdyP2 How it works: 1️⃣ Customer places an order → POST /orders/request → Publishes to topic-received-orders 2️⃣ Payment service picks it up → confirms via POST /payments/confirm → Publishes to topic-approved-orders 3️⃣ Order gets shipped → POST /orders/ship → Publishes to topic-delivering-orders 4️⃣ StatusListener reacts to all 3 topics simultaneously and updates the order status in real time. Design Patterns applied: → Strategy Pattern Each Kafka topic has its own dedicated handler class (HandleReceiveOrderEvent, HandleApprovedOrderEvent, HandleDeliveringOrderEvent), each implementing the same HandleOrderEvent interface. This isolates behavior per event type. → Factory Pattern HandleOrderEventFactory receives the incoming topic name and returns the correct handler, no if/else chains scattered across the codebase. → Dependency Inversion Principle (DIP) No "new" keyword for services or handlers. Spring manages all dependencies via constructor injection, keeping every component loosely coupled and easily testable. What Kafka UI showed: • 3 main topics flowing in sequence • Retry and DLT topics auto-configured for resilience • payment-group and status-group consumers both STABLE throughout Stack & Tools: • Java + Spring Boot • Apache Kafka (event streaming) • Kafka UI (topic & consumer monitoring) • Springdoc OpenAPI / Swagger UI (REST docs) • Lombok (boilerplate reduction) • Docker (Kafka + Kafka UI) #Java #SpringBoot #Kafka #DesignPatterns #EventDriven #Backend #SoftwareEngineering #CleanCode #Microservices
To view or add a comment, sign in
-
Learning and implementing REST APIs with Spring Boot What's happening here: @RestController :- marks this class as a REST API handler @RequestMapping("/employee") :- base URL for all endpoints @Autowired :- injects the Service layer dependency GET /display :- a simple test endpoint to verify the API is live POST /save :- accepts Employee data as JSON and saves to DB GET /getAll :- fetches all employee records from the database Implementing Dependency Injection and a structured Layered Architecture has highlighted the importance of writing clean, maintainable code. #REST #API #BackendDevelopment #SpringBoot #Java
To view or add a comment, sign in
-
-
🚀 Day 32 – Java Backend Journey | Kafka Retry & Error Handling Today I explored retry mechanisms and error handling in Kafka consumers, which are essential for building fault-tolerant and reliable event-driven systems. 🔹 What I practiced today I implemented strategies to handle failures when processing Kafka messages and ensure that messages are not lost. 🔹 Why Retry is Needed? Sometimes message processing can fail due to: • Temporary system issues • Database downtime • Network failures Instead of losing data, we retry processing the message. 🔹 Retry Mechanism (Spring Kafka) Using retry configuration: @KafkaListener(topics = "user-topic", groupId = "group-1") public void consume(String message) { if (message.contains("fail")) { throw new RuntimeException("Simulated failure"); } System.out.println("Processed: " + message); } With retry enabled, Kafka will re-attempt processing before marking it as failed. 🔹 Error Handling Handled exceptions to avoid breaking the consumer: try { // process message } catch (Exception e) { System.out.println("Error occurred: " + e.getMessage()); } 🔹 Dead Letter Topic (DLQ) If retries fail, the message can be sent to a Dead Letter Topic for later analysis. Flow: Main Topic → Retry → Dead Letter Topic 🔹 What I learned • How retry improves reliability of message processing • Importance of handling failures gracefully • Use of Dead Letter Topics (DLQ) for failed messages • Building resilient event-driven systems 🔹 Why this is important ✔ Prevents data loss ✔ Handles temporary failures ✔ Improves system reliability ✔ Essential for production systems 🔹 Key takeaway Retry and error handling are critical for ensuring that Kafka consumers process messages reliably, even in the presence of failures. 📌 Next step: Explore idempotency and message ordering in Kafka. #Java #SpringBoot #Kafka #BackendDevelopment #EventDrivenArchitecture #Microservices #SoftwareEngineering #LearningInPublic #JavaDeveloper #100DaysOfCode
To view or add a comment, sign in
-
-
Java Spring Boot Annotations in a Nutshell https://lnkd.in/g7BmyE3E A technical overview of the essential Java Spring Boot Annotations, serving as a comprehensive "nutshell" guide for modern backend development. As Spring Boot continues to dominate the enterprise ecosystem, mastering its annotation-driven configuration is critical for building scalable, decoupled, and maintainable microservices. => Core Framework Annotations: Analyzing @SpringBootApplication, @Component, and @Bean for managing application context and dependency injection. => Web and REST Integration: Demonstrating the use of @RestController, @RequestMapping, and @PathVariable to streamline API development. => Data and Configuration: Leveraging @Service, @Repository, and @Value to enforce clean architectural layers and externalize properties. #codechallenge #programming #CODE #Coding #code #programmingtips #java #JAVAFullStack #spring #springframework #Springboot #springbootdeveloper #Maven #gradle #annotations #controller #service #dependencyInjection
To view or add a comment, sign in
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development