Mastering Garbage Collection in Java
Build High-Performance Applications by Understanding Memory Management
Move beyond surface-level Java development and gain mastery over the memory management system that powers your applications.
253 pages12 chaptersNov 17, 2025Java
About this book
This book equips you with the knowledge to diagnose performance bottlenecks, optimize garbage collection behavior, and build applications that run efficiently at scale. You'll explore how the JVM manages memory, why garbage collection pauses happen, and how different algorithms handle object lifecycle management. Through practical examples and real-world scenarios, you'll learn to read GC logs, interpret metrics, and make data-driven tuning decisions. Whether you're dealing with latency-sensitive microservices, high-throughput batch systems, or memory-constrained environments, you'll understand the trade-offs and strategies that matter. This comprehensive guide bridges the gap between theoretical understanding and practical application, giving you the confidence to optimize your Java applications and troubleshoot memory-related issues with precision.
Table of contents
- IntroductionWhy Garbage Collection Matters, What You'll Learn in This Book, How to Use This Book, Prerequisites and AssumptionsRead below
- Chapter 1: Memory Management FundamentalsUnderstanding JVM Memory Structure, Heap vs. Stack: Key Differences, The Object Lifecycle in Java, How Memory Allocation Works
- Chapter 2: The Generational HypothesisThe Generational Principle Explained, Young Generation: Where Objects Are Born, Old Generation: Long-Lived Objects, Why Generational Design Improves Performance
- Chapter 3: Core Garbage Collection AlgorithmsMark-Sweep: The Foundation, Mark-Compact: Eliminating Fragmentation, Copying Algorithm: Speed Through Simplicity, Comparing Algorithms: Trade-offs and Use Cases
- Chapter 4: Stop-the-World Pauses and ConcurrencyUnderstanding Stop-the-World Pauses, How Pauses Impact Application Performance, Concurrent Garbage Collection Techniques, Strategies for Reducing Pause Times
- Chapter 5: The Serial, Parallel, and CMS CollectorsSerial Collector: Single-Threaded Simplicity, Parallel Collector: Throughput Optimization, CMS Collector: Low-Latency Focus, Choosing the Right Collector for Your Workload
- Chapter 6: G1 Garbage Collector: The Modern StandardG1GC Design and Architecture, Regions: A New Approach to Heap Organization, G1 Collection Phases and Behavior, Tuning G1GC for Your Application
- Chapter 7: Low-Latency Collectors: ZGC and ShenandoahZGC: Ultra-Low Pause Times, Shenandoah: Concurrent Compaction, Understanding Latency Guarantees, When to Use Low-Latency Collectors
- Chapter 8: Memory Leaks and Object RetentionWhat Constitutes a Memory Leak in Java, Common Memory Leak Patterns, Detecting Memory Leaks with Tools, Preventing Memory Leaks Through Design
- Chapter 9: Reading and Interpreting GC LogsGC Log Basics and Configuration, Parsing and Understanding Log Output, Key Metrics to Monitor, Tools for GC Log Analysis
- Chapter 10: Heap Sizing and ConfigurationPrinciples of Heap Sizing, Initial Heap Size vs. Maximum Heap Size, Sizing for Different Workloads, Monitoring and Adjusting Heap Usage
- Chapter 11: GC Tuning in PracticeA Systematic Approach to GC Tuning, Establishing Baseline Metrics, Running Controlled Tuning Experiments, Applying Tuning Changes to Production
- Chapter 12: Real-World Scenarios and Case StudiesOptimizing High-Throughput Systems, Tuning Latency-Sensitive Applications, Managing Memory-Constrained Environments
- ConclusionKey Takeaways, Continuing Your GC Mastery Journey
- Glossary
- Further Reading and Resources
Introduction
Memory management sits at the heart of every Java application, yet it remains one of the most misunderstood aspects of the platform. When your application slows to a crawl, when response times spike unpredictably, or when you see the dreaded OutOfMemoryError, the culprit often lies in how the Java Virtual Machine manages memory and reclaims unused objects. Understanding garbage collection transforms you from a developer who reacts to memory problems into one who anticipates and prevents them. This knowledge separates applications that merely function from those that perform reliably under real-world conditions.
The Java platform's automatic memory management represents both a blessing and a challenge. Unlike languages where you manually allocate and free memory, Java handles this complexity for you through garbage collection. This automation eliminates entire categories of bugs like dangling pointers and double-free errors that plague manual memory management. However, this convenience comes with a trade-off: you surrender direct control over when and how memory gets reclaimed. The garbage collector makes decisions that profoundly impact your application's performance, and without understanding these decisions, you're flying blind.
Modern Java applications face increasingly demanding requirements. Microservices architectures require predictable latency with strict service-level agreements. High-frequency trading systems cannot tolerate pause times measured in milliseconds. Big data processing pipelines must maintain throughput while handling massive heaps. Container deployments impose memory constraints that demand efficient utilization. Each scenario presents unique challenges that generic garbage collection settings cannot address. This book equips you with the knowledge to meet these challenges head-on, making informed decisions about memory management that align with your specific requirements.
The landscape of garbage collection has evolved dramatically over Java's history. Early collectors prioritized simplicity and correctness over performance. As applications grew more complex and demanding, the JVM introduced collectors optimized for different workloads: throughput-oriented collectors for batch processing, low-latency collectors for interactive applications, and modern collectors that balance multiple concerns. Understanding this evolution helps you appreciate why multiple collectors exist and how to choose among them. The garbage collector that served your application well at small scale might become a bottleneck as you grow, and recognizing these inflection points prevents performance crises.
Why Garbage Collection Matters
Garbage collection directly determines three critical performance characteristics of your application: throughput, latency, and memory footprint. Throughput measures how much work your application completes over time, and garbage collection consumes CPU cycles that could otherwise execute your business logic. A poorly tuned collector might spend thirty percent of CPU time on memory management, effectively reducing your application's capacity by nearly a third. For high-throughput systems processing millions of transactions daily, this overhead translates directly into infrastructure costs and capacity planning. Understanding GC behavior lets you reclaim these lost cycles and maximize the value of your hardware investments.
Latency concerns dominate modern application development, particularly in user-facing systems where response time directly impacts user experience and business metrics. When the garbage collector runs, it often pauses your application threads—these stop-the-world pauses freeze all application activity while the collector performs its work. A pause lasting several hundred milliseconds might seem brief, but it violates service-level agreements, triggers timeouts in distributed systems, and creates perceptible delays for users. Consider an e-commerce checkout flow where a GC pause causes a payment processing timeout: the technical issue cascades into lost revenue and damaged customer trust. Mastering garbage collection means controlling these pauses and ensuring predictable response times.
Memory footprint affects both cost and scalability in modern deployment environments. Cloud infrastructure charges by memory allocation, making efficient memory usage a direct cost optimization. Container orchestration platforms like Kubernetes allocate resources based on declared limits, and exceeding these limits results in pod eviction and service disruption. An application that uses twice the necessary heap size costs twice as much to run and reduces deployment density by half. Beyond cost, memory efficiency determines how many application instances fit on a single host, affecting both horizontal scalability and resource utilization. Proper garbage collection tuning helps you find the sweet spot between memory usage and performance.
The relationship between these three characteristics involves fundamental trade-offs that you must navigate based on your application's priorities. Optimizing for maximum throughput often increases pause times, as throughput-oriented collectors batch work for efficiency. Minimizing latency typically reduces throughput and increases memory overhead, as low-latency collectors perform more work concurrently with application threads. Reducing memory footprint can increase both pause frequency and duration, as smaller heaps fill faster and require more aggressive collection. No single configuration optimizes all three dimensions simultaneously—understanding these trade-offs lets you make conscious decisions aligned with your application's requirements rather than accepting default behavior that may not suit your needs.
Garbage collection problems manifest in subtle ways that complicate diagnosis without proper understanding. An application might perform well in development with small datasets but degrade in production under realistic load. Performance might be acceptable most of the time but exhibit periodic slowdowns that correlate with GC activity. Memory usage might grow steadily over time, suggesting a leak, when the actual problem involves object retention patterns that the collector cannot address. These symptoms often lead developers down wrong paths, attempting to optimize application code when the real issue lies in memory management configuration. Recognizing GC-related performance patterns saves countless hours of misdirected troubleshooting.
The impact of garbage collection extends beyond individual application performance to affect system-level behavior in distributed architectures. In microservices environments, GC pauses in one service can trigger cascading failures as dependent services time out and retry. Load balancers might mark instances as unhealthy during long GC pauses, causing traffic shifts that overload remaining instances. Database connection pools can exhaust during pauses, creating bottlenecks that persist after the pause ends. Message queues might fill with unprocessed messages, creating backpressure throughout the system. Understanding garbage collection in distributed contexts helps you design resilient systems that gracefully handle the inevitable pauses rather than amplifying their impact.
Modern application development increasingly involves frameworks and libraries that abstract away low-level details, but these abstractions cannot hide garbage collection behavior. Popular frameworks like Spring Boot, Hibernate, and various reactive programming libraries create objects with specific lifecycle patterns that interact with garbage collection in predictable ways. A framework that caches aggressively might prevent object collection, while one that creates many short-lived objects might stress the young generation. Understanding how your technology stack interacts with garbage collection helps you configure both the framework and the JVM for optimal performance. This knowledge proves particularly valuable when framework defaults don't align with your deployment environment.
The business case for garbage collection expertise extends beyond technical performance metrics. Application downtime costs money, whether through lost transactions, violated SLAs with financial penalties, or damaged reputation. Infrastructure costs scale with inefficiency—an application requiring twice the memory or CPU due to poor GC configuration doubles hosting expenses. Developer productivity suffers when teams spend time firefighting performance issues rather than building features. Organizations that invest in GC knowledge reduce these costs while improving reliability and user experience. For individual developers, this expertise differentiates you in the job market and enables you to solve problems that others find mysterious and intractable.
What You'll Learn in This Book
This book builds your understanding systematically, starting with fundamental concepts and progressing to advanced tuning techniques. You'll begin by exploring how the JVM structures memory and manages object lifecycles, establishing the foundation necessary to understand garbage collection behavior. These fundamentals include the distinction between heap and stack memory, how objects move through different memory regions, and why the JVM organizes memory into generations. Without this foundation, garbage collection appears as mysterious behavior; with it, you'll see the logical design decisions that drive collector implementations. Each concept builds on previous ones, creating a coherent mental model of memory management.
The core of the book examines garbage collection algorithms and collectors in depth, explaining not just what they do but why they work that way. You'll understand the mark-sweep, mark-compact, and copying algorithms that form the building blocks of all collectors. Then you'll explore specific collector implementations: the Serial collector's simplicity, the Parallel collector's throughput focus, CMS's low-latency approach, G1GC's balanced design, and the ultra-low-latency ZGC and Shenandoah collectors. For each collector, you'll learn its architecture, behavior patterns, configuration options, and ideal use cases. This knowledge enables you to select the right collector for your workload rather than accepting defaults that may not suit your needs.
Practical skills form a major focus throughout the book, ensuring you can apply theoretical knowledge to real applications. You'll learn to read and interpret garbage collection logs, extracting meaningful metrics from verbose output. The book covers tools for analyzing GC behavior, from built-in JVM utilities to third-party analysis platforms. You'll develop a systematic methodology for GC tuning: establishing baselines, forming hypotheses, running controlled experiments, and validating results. These practical skills transform abstract knowledge into actionable capabilities, letting you diagnose problems in production systems and optimize performance with confidence.
Memory leaks in Java represent a particularly insidious class of problems that this book addresses comprehensively. You'll learn what constitutes a memory leak in a garbage-collected language—not the traditional definition of unreachable allocated memory, but rather unintentional object retention that prevents collection. Common leak patterns include static collections that grow unbounded, listener registrations that never unregister, ThreadLocal variables that persist beyond their useful life, and classloader leaks in application servers. The book provides concrete examples of each pattern, explains how to detect them using heap analysis tools, and demonstrates prevention strategies through proper design. This knowledge helps you avoid creating leaks and quickly identify them when they occur.
Heap sizing and configuration receive detailed treatment, as these decisions fundamentally affect garbage collection behavior. You'll learn principles for determining appropriate heap sizes based on application characteristics, workload patterns, and deployment constraints. The book explains the relationship between initial and maximum heap sizes, the implications of different sizing strategies, and how to monitor heap usage to validate your decisions. You'll understand how heap size interacts with collector choice and tuning parameters, creating a holistic view of memory configuration. Specific guidance for different scenarios—containerized deployments, memory-constrained environments, and large-heap applications—provides practical starting points for your own configurations.
Real-world case studies throughout the book demonstrate how concepts apply to actual applications and problems. You'll see examples of optimizing high-throughput batch processing systems where maximizing work completion matters most. Latency-sensitive applications like REST APIs and interactive services illustrate techniques for minimizing pause times and ensuring predictable response times. Memory-constrained environments such as container deployments show how to balance performance with resource limits. Each case study includes the problem context, diagnostic process, solution approach, and results achieved. These examples bridge the gap between theoretical understanding and practical application, showing you how experienced practitioners approach real problems.
The book addresses the evolution of garbage collection across Java versions, helping you understand how capabilities have improved and what options your Java version supports. Java 8 applications have different collector choices than Java 11 or Java 17 deployments. New collectors like ZGC and Shenandoah became production-ready in recent versions, offering capabilities unavailable in older releases. Understanding version-specific features helps you make informed decisions about Java upgrades and lets you leverage new capabilities when they become available. The book notes version requirements for specific features, ensuring you don't attempt configurations unsupported by your runtime.
Throughout the book, you'll develop an understanding of trade-offs that characterizes expert-level knowledge. Every tuning decision involves compromises: faster young generation collection might increase old generation pressure, larger heaps reduce collection frequency but increase pause duration, concurrent collection reduces pause times but increases CPU overhead. The book explicitly discusses these trade-offs for each technique and configuration option, helping you make informed decisions rather than blindly applying recommendations. This nuanced understanding separates developers who can tune for their specific context from those who apply generic advice that may not fit their situation.
How to Use This Book
This book is designed for progressive learning, with each chapter building on concepts introduced in previous ones. If you're new to garbage collection or want comprehensive understanding, reading sequentially from beginning to end provides the most coherent learning experience. The early chapters establish fundamental concepts that later chapters assume you understand. Skipping ahead to advanced topics without this foundation may leave you confused about terminology and concepts. However, the book's structure also supports targeted reading if you have specific needs or existing knowledge. Each chapter begins with a brief overview of its content and prerequisites, helping you assess whether to read it thoroughly or skim for new information.
For readers facing immediate production issues, the book includes guidance for rapid problem-solving alongside comprehensive explanations. If you're experiencing memory leaks, Chapter 8 provides diagnostic techniques and common patterns you can apply immediately. If pause times are causing problems, Chapter 4 explains stop-the-world behavior and mitigation strategies. The chapter on reading GC logs (Chapter 9) helps you extract meaningful information from your application's current behavior. While these targeted readings provide immediate value, returning to earlier chapters when time permits will deepen your understanding and help you prevent future problems rather than just reacting to current ones.
Hands-on experimentation amplifies the value of reading this book. The concepts and techniques described become concrete when you apply them to actual applications, even simple test programs. Consider creating small Java applications that exhibit specific behaviors discussed in each chapter: an application that creates many short-lived objects to stress the young generation, one that retains objects to trigger old generation collection, or one that demonstrates a memory leak pattern. Running these applications with different collectors and configurations, then examining the resulting GC logs, transforms abstract concepts into observable behavior. The book includes suggestions for experiments throughout, but your own curiosity and exploration will yield the deepest learning.
The book's code examples and configuration snippets are designed for practical use, not just illustration. When you see a JVM flag or configuration option, try it in your own environment. When the book shows a log analysis technique, apply it to your application's logs. When a case study describes a tuning approach, adapt it to your situation. This active engagement with the material accelerates learning and builds confidence in your ability to apply these techniques. Keep a test environment available where you can safely experiment without affecting production systems. The ability to quickly test hypotheses and observe results proves invaluable when tuning real applications.
Different readers will find different chapters most relevant based on their current challenges and interests. Developers working with microservices and containerized deployments will find the sections on heap sizing and memory-constrained environments particularly applicable. Those building high-throughput data processing systems will focus on throughput-oriented collectors and optimization techniques. Teams supporting latency-sensitive applications will dive deep into low-latency collectors and pause time reduction strategies. The book's comprehensive coverage ensures that regardless of your specific context, you'll find relevant, actionable guidance. Use the table of contents and chapter overviews to identify sections most pertinent to your immediate needs.
This book serves as both a learning resource and a reference you'll return to over time. During initial reading, focus on understanding concepts and building your mental model of garbage collection. Later, when facing specific tuning decisions or troubleshooting particular problems, return to relevant chapters for detailed guidance. The book's organization supports this dual use: conceptual explanations provide learning value, while specific techniques, configurations, and troubleshooting approaches serve as reference material. Consider marking sections particularly relevant to your work or keeping notes about which chapters address which types of problems. This investment in organization pays dividends when you need quick answers under pressure.
Collaboration and discussion enhance learning from technical material like this book. If you work with a team, consider reading chapters together and discussing how concepts apply to your shared applications. Different team members will notice different implications and applications of the material. Discussing real problems your team has faced in light of the book's explanations often yields insights that individual reading might miss. If you're learning independently, online communities focused on Java performance provide venues for discussing concepts and getting feedback on your understanding. Teaching concepts to others, whether formally or informally, solidifies your own understanding and reveals gaps in your knowledge.
The book includes references to additional resources, tools, and documentation throughout. These references aren't just academic citations—they point to materials that extend and complement the book's content. Official JVM documentation provides authoritative details about specific flags and behaviors. Tool documentation helps you leverage analysis utilities effectively. Research papers explain the theoretical foundations of algorithms and techniques. Blog posts and articles from practitioners offer additional perspectives and case studies. Following these references based on your interests and needs enriches your understanding beyond what any single book can provide. Consider maintaining a collection of particularly useful resources you discover through these references.
Prerequisites and Assumptions
This book assumes you have intermediate Java development experience and foundational knowledge of the language. You should be comfortable reading and writing Java code, understanding object-oriented programming concepts, and working with common Java development tools. Familiarity with basic JVM concepts like the classpath, JAR files, and command-line execution helps you follow examples and apply techniques. You don't need to be an expert Java developer, but you should have moved beyond beginner tutorials and worked on real applications. If you've built and deployed Java applications, even simple ones, you have sufficient background to benefit from this book.
The book does not assume prior knowledge of garbage collection, memory management internals, or JVM tuning. These topics form the core content, and the book builds your understanding from first principles. If you've encountered garbage collection concepts before, you'll find the early chapters review familiar territory while adding depth and nuance. If these topics are entirely new, the progressive structure ensures you develop necessary foundations before tackling advanced material. Previous experience with performance tuning or troubleshooting helps you appreciate the practical value of concepts, but it's not required—the book explains why these techniques matter alongside how they work.
Some familiarity with command-line tools and system administration concepts proves helpful, as garbage collection tuning involves JVM flags, log file analysis, and monitoring tools. You should be comfortable running Java applications from the command line with various options and flags. Basic understanding of operating system concepts like processes, threads, and memory helps you grasp how the JVM interacts with the underlying system. If you've worked with application servers, build tools like Maven or Gradle, or deployment platforms, you'll find it easier to apply tuning techniques in realistic contexts. However, the book explains necessary concepts rather than assuming deep systems knowledge.
The book uses examples and configurations applicable across different operating systems and deployment environments. While specific commands might vary slightly between Windows, Linux, and macOS, the concepts and techniques apply universally. Most examples use Linux-style command syntax, as it's common in server deployments, but Windows users can easily adapt them. The book notes platform-specific considerations where they matter, such as differences in memory management behavior or tool availability. Your development environment—whether local workstation, virtual machine, or cloud instance—doesn't significantly affect your ability to follow along and experiment with concepts.
No specific Java version is required, but the book covers features and collectors available in Java 8 through Java 17 and beyond. Many concepts apply across all versions, as fundamental garbage collection principles remain consistent. Version-specific features, like ZGC's availability starting in Java 11 or improvements to G1GC across versions, are clearly marked. If you're working with Java 8, you'll understand which collectors and options are available to you. If you're using newer versions, you'll learn about additional capabilities and improvements. The book helps you make the most of whatever Java version your organization uses while understanding what newer versions offer.
Access to a Java development environment where you can run applications and experiment with configurations is highly valuable but not strictly required. You can learn concepts by reading alone, but hands-on experimentation dramatically improves understanding and retention. A simple setup with the JDK installed and ability to run command-line Java applications suffices—you don't need elaborate infrastructure or powerful hardware. Even a modest laptop can run the examples and experiments suggested throughout the book. If you're working in a restricted environment where you cannot install software or modify configurations, you'll still gain valuable conceptual knowledge, though practical application will be limited until you have a suitable environment.
The book assumes you have motivation to understand garbage collection deeply rather than just applying quick fixes. This material requires intellectual engagement and willingness to grapple with complex systems. If you're looking for a simple checklist of flags to copy without understanding, this book will frustrate you—it emphasizes understanding over rote application. However, if you want to truly master memory management and make informed decisions about your applications, you'll find the investment worthwhile. The book respects your intelligence and time by providing thorough explanations that enable independent problem-solving rather than creating dependency on external expertise.
Finally, the book assumes you have access to your application's configuration and logs, or at least the ability to create test applications where you control these aspects. Many techniques involve analyzing GC logs, adjusting JVM flags, and observing resulting behavior. If you're working in an environment where you cannot access logs or modify configurations, your ability to apply techniques will be limited. However, understanding concepts still provides value: you'll better understand your application's behavior, communicate more effectively with those who can make changes, and prepare yourself for future roles with greater autonomy. The knowledge remains valuable even if immediate application is constrained by your current environment.
This is the end of the free sample. The full book has 12 chapters.
Want this book written for you?
Tell us your goals and background, and get your own version of this book, tailored by AI to you.
Benefits of AI-tailored books
- Read one book, not ten:
- all the Java knowledge you need, gathered into a single book.
- Save days of learning:
- tell us your goals, choose your topics, and the whole book is built around them.
- Learn effortlessly:
- Java book written for your specific background and expertise.
- Understand at a glance:
- includes charts, tables, timelines, checklists, decision trees, and more.
- Stay current:
- written the day you order it, not years ago.
- Trust what you read:
- every book is checked for accuracy, with real research when your subject needs it.
Create your unique book in 3 steps
- 1. Select your focus
Select the focus of your Java book and share your background
- 2. Personalize your book
Specify your goals and choose sub-topics to include
- 3. Get your tailored book
Your book is ready in 10 minutes. Read it online, download as EPUB or PDF, or send to Kindle.
Frequently asked questions
- What is TailoredRead?
TailoredRead creates complete, full-length nonfiction ebooks, written specifically for you. Tell us what you want to learn and why, and TailoredRead writes you a complete ebook on it, with charts, tables, and diagrams throughout. Read it online, on Kindle, or on any e-reader, or download it as a PDF or EPUB. Every book is written fresh the day you order it.
- How is the book tailored to me?
Before anything is written, you answer a few short questions about your goals, your background, and the topics you care about. Your book is then planned around your answers: written at your level, focused on your goals, and covering the topics you chose, instead of the one-size-fits-all book a store sells everyone.
- Will it read like generic AI content?
No. Your book isn't a chat transcript: it's planned chapter by chapter before a single word is written, told in a clear book voice, and explains ideas visually with charts, tables, and diagrams. After writing, every book goes through an editorial pass that polishes chapters so the book reads consistent from start to finish. Judge for yourself: browse thousands of sample books on our Explore Books page.
- How accurate is the content?
Our AI first checks whether your subject needs live research. Niche and fast-moving subjects are researched before writing, and the book plan and chapters are grounded in what it finds. After writing, every book goes through a quality pass that checks its facts and consistency, and researched books list their sources in a Notes section at the back.
- How long is the book?
You choose the length: Comprehensive (250-300 pages), Detailed (150-200 pages), Essential (70-100 pages), or Short (30-50 pages).
- Does the book include visuals?
Yes. Every book includes charts, tables, and diagrams: timelines, checklists, step-by-step guides, decision trees, comparison tables, matrices, and bar charts. A typical book includes dozens of these visual elements.
- Can I read it on Kindle? What formats can I download?
Yes. Every book can be read in our online reader or downloaded as a PDF or EPUB. The EPUB can be opened with Kindle, Apple Books, Kobo, and any e-reader. The Commercial and Author licenses also include an editable Word (DOCX) and Markdown download.
- How much does it cost?
About the price of a regular ebook. The exact price depends on your book's length and complexity, from $2 for the shortest books to $35 for the most comprehensive, and it's shown when you review your book, before you commit to anything. Each book is a one-time purchase, yours to keep, no subscription. Licenses that let you share, teach, or publish your book range from $35.99 to $49.99.
- Can I preview the book before purchasing?
Before you pay, you'll see what your book will cover: the title, a detailed description, the estimated length, and the complete chapter-by-chapter table of contents, so you know what you're getting before you decide. The full text itself is written after you purchase.
- How long does it take to create a book?
About 10 minutes. You can start reading the opening chapters while the rest is still being written.


