Statistics
50
Views
0
Downloads
0
Donations
Support
Share
Uploader

高宏飞

Shared on 2025-12-07

AuthorScott Oaks

Coding and testing are generally considered separate areas of expertise. In this practical book, Java expert Scott Oaks takes the approach that anyone who works with Java should be adept at understanding how code behaves in the Java Virtual Machine—including the tunings likely to help performance. This updated second edition helps you gain in-depth knowledge of Java application performance using both the JVM and the Java platform. Developers and performance engineers alike will learn a variety of features, tools, and processes for improving the way the Java 8 and 11 LTS releases perform. While the emphasis is on production-supported releases and features, this book also features previews of exciting new technologies such as ahead-of-time compilation and experimental garbage collections. • Understand how various Java platforms and compilers affect performance • Learn how Java garbage collection works • Apply four principles to obtain best results from performance testing • Use the JDK and other tools to learn how a Java application is performing • Minimize the garbage collector’s impact through tuning and programming practices • Tackle performance issues in Java APIs • Improve Java-driven database application performance

Tags
No tags
ISBN: 1492056111
Publisher: O'Reilly Media
Publish Year: 2020
Language: 英文
Pages: 450
File Format: PDF
File Size: 9.4 MB
Support Statistics
¥.00 · 0times
Text Preview (First 20 pages)
Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

Second Edition Scott Oaks Java Performance In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond
Scott Oaks Java Performance In-Depth Advice for Tuning and Programming Java 8, 11, and Beyond SECOND EDITION Boston Farnham Sebastopol TokyoBeijing
978-1-492-05611-9 [LSI] Java Performance by Scott Oaks Copyright © 2020 Scott Oaks. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Acquisitions Editor: Suzanne McQuade Developmental Editor: Amelia Blevins Production Editor: Beth Kelly Copyeditor: Sharon Wilkey Proofreader: Kim Wimpsett Indexer: WordCo Inc. Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Rebecca Demarest April 2014: First Edition February 2020: Second Edition Revision History for the Second Edition 2020-02-11: First Release See http://oreilly.com/catalog/errata.csp?isbn=9781492056119 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Java Performance, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the author, and do not represent the publisher’s views. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights.
Table of Contents Preface. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ix 1. Introduction. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 A Brief Outline 2 Platforms and Conventions 2 Java Platforms 3 Hardware Platforms 5 The Complete Performance Story 8 Write Better Algorithms 9 Write Less Code 9 Oh, Go Ahead, Prematurely Optimize 10 Look Elsewhere: The Database Is Always the Bottleneck 12 Optimize for the Common Case 13 Summary 13 2. An Approach to Performance Testing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Test a Real Application 15 Microbenchmarks 15 Macrobenchmarks 20 Mesobenchmarks 22 Understand Throughput, Batching, and Response Time 24 Elapsed Time (Batch) Measurements 24 Throughput Measurements 25 Response-Time Tests 26 Understand Variability 30 Test Early, Test Often 34 Benchmark Examples 36 Java Microbenchmark Harness 37 iii
Common Code Examples 44 Summary 48 3. A Java Performance Toolbox. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Operating System Tools and Analysis 49 CPU Usage 50 The CPU Run Queue 54 Disk Usage 55 Network Usage 57 Java Monitoring Tools 58 Basic VM Information 60 Thread Information 63 Class Information 63 Live GC Analysis 63 Heap Dump Postprocessing 64 Profiling Tools 64 Sampling Profilers 64 Instrumented Profilers 69 Blocking Methods and Thread Timelines 70 Native Profilers 72 Java Flight Recorder 74 Java Mission Control 74 JFR Overview 76 Enabling JFR 82 Selecting JFR Events 86 Summary 88 4. Working with the JIT Compiler. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 Just-in-Time Compilers: An Overview 89 HotSpot Compilation 91 Tiered Compilation 93 Common Compiler Flags 94 Tuning the Code Cache 94 Inspecting the Compilation Process 96 Tiered Compilation Levels 100 Deoptimization 101 Advanced Compiler Flags 105 Compilation Thresholds 105 Compilation Threads 107 Inlining 109 Escape Analysis 110 CPU-Specific Code 112 iv | Table of Contents
Tiered Compilation Trade-offs 113 The GraalVM 115 Precompilation 116 Ahead-of-Time Compilation 116 GraalVM Native Compilation 118 Summary 120 5. An Introduction to Garbage Collection. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Garbage Collection Overview 121 Generational Garbage Collectors 123 GC Algorithms 126 Choosing a GC Algorithm 130 Basic GC Tuning 138 Sizing the Heap 138 Sizing the Generations 141 Sizing Metaspace 144 Controlling Parallelism 146 GC Tools 147 Enabling GC Logging in JDK 8 148 Enabling GC Logging in JDK 11 148 Summary 152 6. Garbage Collection Algorithms. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 Understanding the Throughput Collector 153 Adaptive and Static Heap Size Tuning 156 Understanding the G1 Garbage Collector 160 Tuning G1 GC 170 Understanding the CMS Collector 174 Tuning to Solve Concurrent Mode Failures 179 Advanced Tunings 182 Tenuring and Survivor Spaces 182 Allocating Large Objects 186 AggressiveHeap 193 Full Control Over Heap Size 195 Experimental GC Algorithms 197 Concurrent Compaction: ZGC and Shenandoah 197 No Collection: Epsilon GC 200 Summary 201 7. Heap Memory Best Practices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Heap Analysis 203 Heap Histograms 204 Table of Contents | v
Heap Dumps 205 Out-of-Memory Errors 210 Using Less Memory 215 Reducing Object Size 215 Using Lazy Initialization 219 Using Immutable and Canonical Objects 223 Object Life-Cycle Management 225 Object Reuse 225 Soft, Weak, and Other References 231 Compressed Oops 246 Summary 248 8. Native Memory Best Practices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249 Footprint 249 Measuring Footprint 250 Minimizing Footprint 251 Native Memory Tracking 252 Shared Library Native Memory 256 JVM Tunings for the Operating System 261 Large Pages 261 Summary 265 9. Threading and Synchronization Performance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267 Threading and Hardware 267 Thread Pools and ThreadPoolExecutors 268 Setting the Maximum Number of Threads 269 Setting the Minimum Number of Threads 273 Thread Pool Task Sizes 275 Sizing a ThreadPoolExecutor 275 The ForkJoinPool 278 Work Stealing 283 Automatic Parallelization 285 Thread Synchronization 287 Costs of Synchronization 287 Avoiding Synchronization 291 False Sharing 294 JVM Thread Tunings 299 Tuning Thread Stack Sizes 299 Biased Locking 300 Thread Priorities 300 Monitoring Threads and Locks 301 Thread Visibility 301 vi | Table of Contents
Blocked Thread Visibility 302 Summary 306 10. Java Servers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307 Java NIO Overview 307 Server Containers 309 Tuning Server Thread Pools 309 Async Rest Servers 311 Asynchronous Outbound Calls 314 Asynchronous HTTP 315 JSON Processing 322 An Overview of Parsing and Marshaling 323 JSON Objects 324 JSON Parsing 325 Summary 327 11. Database Performance Best Practices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 329 Sample Database 330 JDBC 330 JDBC Drivers 330 JDBC Connection Pools 333 Prepared Statements and Statement Pooling 334 Transactions 336 Result Set Processing 345 JPA 347 Optimizing JPA Writes 347 Optimizing JPA Reads 349 JPA Caching 353 Spring Data 360 Summary 361 12. Java SE API Tips. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363 Strings 363 Compact Strings 363 Duplicate Strings and String Interning 364 String Concatenation 371 Buffered I/O 374 Classloading 377 Class Data Sharing 377 Random Numbers 381 Java Native Interface 383 Exceptions 386 Table of Contents | vii
Logging 390 Java Collections API 392 Synchronized Versus Unsynchronized 392 Collection Sizing 394 Collections and Memory Efficiency 395 Lambdas and Anonymous Classes 397 Stream and Filter Performance 399 Lazy Traversal 399 Object Serialization 402 Transient Fields 403 Overriding Default Serialization 403 Compressing Serialized Data 406 Keeping Track of Duplicate Objects 408 Summary 411 A. Summary of Tuning Flags. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 413 Index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 423 viii | Table of Contents
Preface When O’Reilly first approached me about writing a book on Java performance tun‐ ing, I was unsure. Java performance, I thought—aren’t we done with that? Yes, I still work on improving the performance of Java (and other) applications on a daily basis, but I like to think that I spend most of my time dealing with algorithmic inefficien‐ cies and external system bottlenecks rather than on anything directly related to Java tuning. A moment’s reflection convinced me that I was (as usual) kidding myself. It is cer‐ tainly true that end-to-end system performance takes up a lot of my time, and that I sometimes come across code that uses an O n2 algorithm when it could use one with O(logN) performance. Still, it turns out that every day I think about garbage collec‐ tion (GC) performance, or the performance of the JVM compiler, or how to get the best performance from Java APIs. That is not to minimize the enormous progress that has been made in the perfor‐ mance of Java and JVMs over the past 20-plus years. When I was a Java evangelist at Sun during the late 1990s, the only real “benchmark” available was CaffeineMark 2.0 from Pendragon software. For a variety of reasons, the design of that benchmark quickly limited its value; yet in its day, we were fond of telling everyone that Java 1.1.8 performance was eight times faster than Java 1.0 performance based on that bench‐ mark. And that was true—Java 1.1.8 had an actual just-in-time compiler, whereas Java 1.0 was pretty much completely interpreted. Then standards committees began to develop more rigorous benchmarks, and Java performance began to be centered around them. The result was a continuous improvement in all areas of the JVM—garbage collection, compilations, and within the APIs. That process continues today, of course, but one of the interesting facts about performance work is that it gets successively harder. Achieving an eightfold increase in performance by introducing a just-in-time compiler was a straightforward matter of engineering, and even though the compiler continues to improve, we’re not going to see an improvement like that again. Parallelizing the garbage collector was a ix
huge performance improvement, but more recent changes have been more incremental. This is a typical process for applications (and the JVM itself is just another applica‐ tion): in the beginning of a project, it’s easy enough to find architectural changes (or code bugs) that, when addressed, yield huge performance improvements. In a mature application, finding such performance improvements is rare. That precept was behind my original concern that, to a large extent, the engineering world might be done with Java performance. A few things convinced me I was wrong. First is the number of questions I see daily about how this or that aspect of the JVM performs under certain circumstances. New engineers come to Java all the time, and JVM behavior remains complex enough in certain areas that a guide to its operation is still beneficial. Second is that environmental changes in computing seem to have altered the performance concerns that engineers face today. Over the past few years, performance concerns have become bifurcated. On the one hand, very large machines capable of running JVMs with very large heaps are now commonplace. The JVM has moved to address those concerns with a new garbage collector (G1), which—as a new technology—requires a little more hand-tuning than traditional collectors. At the same time, cloud computing has renewed the impor‐ tance of small, single-CPU machines: you can go to Oracle or Amazon or a host of other companies and cheaply rent a single CPU machine to run a small application server. (You’re not actually getting a single-CPU machine: you’re getting a virtual OS image on a very large machine, but the virtual OS is limited to using a single CPU. From the perspective of Java, that turns out to be the same as a single-CPU machine.) In those environments, correctly managing small amounts of memory turns out to be quite important. The Java platform also continues to evolve. Each new edition of Java provides new language features and new APIs that improve the productivity of developers—if not always the performance of their applications. Best practice use of these language fea‐ tures can help differentiate between an application that sizzles and one that plods along. And the evolution of the platform brings up interesting performance ques‐ tions: there is no question that using JSON to exchange information between two programs is much simpler than coming up with a highly optimized proprietary pro‐ tocol. Saving time for developers is a big win—but making sure that productivity win comes with a performance win (or at least breaks even) is the real goal. x | Preface
Who Should (and Shouldn’t) Read This Book This book is designed for performance engineers and developers who are looking to understand how various aspects of the JVM and the Java APIs impact performance. If it is late Sunday night, your site is going live Monday morning, and you’re looking for a quick fix for performance issues, this is not the book for you. If you are new to performance analysis and are starting that analysis in Java, this book can help you. Certainly my goal is to provide enough information and context that novice engineers can understand how to apply basic tuning and performance princi‐ ples to a Java application. However, system analysis is a broad field. There are a num‐ ber of excellent resources for system analysis in general (and those principles, of course, apply to Java), and in that sense, this book will ideally be a useful companion to those texts. At a fundamental level, though, making Java go really fast requires a deep under‐ standing of how the JVM (and Java APIs) actually work. Hundreds of Java tuning flags exist, and tuning the JVM has to be more than an approach of blindly trying them and seeing what works. Instead, my goal is to provide detailed knowledge about what the JVM and APIs are doing, with the hope that if you understand how those things work, you’ll be able to look at the specific behavior of an application and understand why it is performing badly. Understanding that, it becomes a simple (or at least simpler) task to get rid of undesirable (badly performing) behavior. One interesting aspect to Java performance work is that developers often have a very different background than engineers in a performance or QA group. I know develop‐ ers who can remember thousands of obscure method signatures on little-used Java APIs but who have no idea what the flag -Xmn means. And I know testing engineers who can get every last ounce of performance from setting various flags for the garbage collector but who can barely write a suitable “Hello, World” program in Java. Java performance covers both of these areas: tuning flags for the compiler and garbage collector and so on, and best-practice uses of the APIs. So I assume that you have a good understanding of how to write programs in Java. Even if your primary interest is not in the programming aspects of Java, I do spend a fair amount of time discussing programs, including the sample programs used to provide a lot of the data points in the examples. Still, if your primary interest is in the performance of the JVM itself—meaning how to alter the behavior of the JVM without any coding—then large sections of this book should still be beneficial to you. Feel free to skip over the coding parts and focus on the areas that interest you. And maybe along the way, you’ll pick up some insight into how Java applications can affect JVM performance and start to suggest changes to developers so they can make your performance-testing life easier. Preface | xi
What’s New in the Second Edition Since the first edition, Java has adopted a six-month release cycle with periodic long- term releases; that means the current supported releases that coincide with publica‐ tion are Java 8 and Java 11. Although the first edition covered Java 8, it was quite new at the time. This edition focuses on a much more mature Java 8 and Java 11, with major updates to the G1 garbage collector and Java Flight Recorder. Attention is also given to changes in the way Java behaves in containerized environments. This edition covers new features of the Java platform, including a new microbe‐ nchmarking harness (jmh), new just-in-time compilers, application class data sharing, and new performance tools—as well as coverage of new Java 11 features like compact strings and string concatenation. Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, email addresses, filenames, and file extensions. Constant width Used for program listings, as well as within paragraphs to refer to program ele‐ ments such as variable or function names, databases, data types, environment variables, statements, and keywords. Constant width bold Shows commands or other text that should be typed literally by the user. Constant width italic Shows text that should be replaced with user-supplied values or by values deter‐ mined by context. This element signifies a summary of main points. Using Code Examples Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/ScottOaks/JavaPerformanceTuning. This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not xii | Preface
need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Java Performance by Scott Oaks (O’Reilly). Copyright 2020 Scott Oaks, 978-1-492-05611-9.” If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at http://oreilly.com. O’Reilly Online Learning For more than 40 years, O’Reilly Media has provided technol‐ ogy and business training, knowledge, and insight to help companies succeed. Our unique network of experts and innovators share their knowledge and expertise through books, articles, conferences, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in- depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, please visit http://oreilly.com. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://oreil.ly/java-performance-2e. Preface | xiii
Email bookquestions@oreilly.com to comment or ask technical questions about this book. For more information about our books, courses, conferences, and news, see our web‐ site at http://www.oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://www.youtube.com/oreillymedia Acknowledgments I would like to thank everyone who helped me as I worked on this book. In many ways, this book is an accumulation of knowledge gained over my past 20 years in the Java Performance Group and other engineering groups at Sun Microsystems and Oracle, so the list of people who have provided positive input into this book is quite broad. To all the engineers I have worked with during that time, and particularly to those who patiently answered my random questions over the past year, thank you! I would especially like to thank Stanley Guan, Azeem Jiva, Kim LiChong, Deep Singh, Martijn Verburg, and Edward Yue Shung Wong for their time reviewing draft copies and providing valuable feedback. I am sure that they were unable to find all my errors, though the material here is greatly improved by their input. The second edi‐ tion was improved greatly by the thorough and thoughtful help offered by Ben Evans, Rod Hilton, and Michael Hunger. My colleagues Eric Caspole, Charlie Hunt, and Robert Strout in the Oracle HotSpot performance group patiently helped me with a variety of issues in the second edition as well. The production staff at O’Reilly was, as always, very helpful. I was privileged to work with editor Meg Blanchette on the first edition, and Amelia Blevins thoughtfully and carefully guided the second edition. Thanks for all your encouragement during the process! Finally, I must thank my husband, James, for putting up with the long nights and those weekend dinners where I was in a continual state of distraction. xiv | Preface
CHAPTER 1 Introduction This is a book about the art and science of Java performance. The science part of this statement isn’t surprising; discussions about performance include lots of numbers and measurements and analytics. Most performance engi‐ neers have a background in the sciences, and applying scientific rigor is a crucial part of achieving maximum performance. What about the art part? The notion that performance tuning is part art and part sci‐ ence is hardly new, but it is rarely given explicit acknowledgment in performance dis‐ cussions. This is partly because the idea of “art” goes against our training. But what looks like art to some people is fundamentally based on deep knowledge and experi‐ ence. It is said that magic is indistinguishable from sufficiently advanced technolo‐ gies, and certainly it is true that a cell phone would look magical to a knight of the Round Table. Similarly, the work produced by a good performance engineer may look like art, but that art is really an application of deep knowledge, experience, and intuition. This book cannot help with the experience and intuition part of that equation, but it can provide the deep knowledge—with the view that applying knowledge over time will help you develop the skills needed to be a good Java performance engineer. The goal is to give you an in-depth understanding of the performance aspects of the Java platform. This knowledge falls into two broad categories. First is the performance of the Java Virtual Machine (JVM) itself: the way that the JVM is configured affects many aspects of a program’s performance. Developers who are experienced in other lan‐ guages may find the need for tuning to be somewhat irksome, though in reality tun‐ ing the JVM is completely analogous to testing and choosing compiler flags during 1
compilation for C++ programmers, or to setting appropriate variables in a php.ini file for PHP coders, and so on. The second aspect is to understand how the features of the Java platform affect per‐ formance. Note the use of the word platform here: some features (e.g., threading and synchronization) are part of the language, and some features (e.g., string handling) are part of the standard Java API. Though important distinctions exist between the Java language and the Java API, in this case they will be treated similarly. This book covers both facets of the platform. The performance of the JVM is based largely on tuning flags, while the performance of the platform is determined more by using best practices within your application code. For a long time, these were considered separate areas of expertise: developers code, and the performance group tests and recommends fixes for performance issues. That was never a particularly useful distinction—anyone who works with Java should be equally adept at understanding how code behaves in the JVM and what kinds of tuning are likely to help its performance. As projects move to a devops model, this distinction is starting to become less strict. Knowledge of the complete sphere is what will give your work the patina of art. A Brief Outline First things first, though: Chapter 2 discusses general methodologies for testing Java applications, including pitfalls of Java benchmarking. Since performance analysis requires visibility into what the application is doing, Chapter 3 provides an overview of some of the tools available to monitor Java applications. Then it is time to dive into performance, focusing first on common tuning aspects: just-in-time compilation (Chapter 4) and garbage collection (Chapter 5 and Chap‐ ter 6). The remaining chapters focus on best-practice uses of various parts of the Java platform: memory use with the Java heap (Chapter 7), native memory use (Chap‐ ter 8), thread performance (Chapter 9), Java server technology (Chapter 10), database access, (Chapter 11), and general Java SE API tips (Chapter 12). Appendix A lists all the tuning flags discussed in this book, with cross-references to the chapter where they are examined. Platforms and Conventions While this book is about the performance of Java, that performance will be influenced by a few factors: the version of Java itself, of course, as well as the hardware and soft‐ ware platforms it is running on. 2 | Chapter 1: Introduction
1 Rarely, differences between the two exist; for example, the AdoptOpenJDK versions of Java contain new garbage collectors in JDK 11. I’ll point out those differences when they occur. Java Platforms This book covers the performance of the Oracle HotSpot Java Virtual Machine (JVM) and the Java Development Kit (JDK), versions 8 and 11. This is also known as Java, Standard Edition (SE). The Java Runtime Environment (JRE) is a subset of the JDK containing only the JVM, but since the tools in the JDK are important for perfor‐ mance analysis, the JDK is the focus of this book. As a practical matter, that means it also covers platforms derived from the OpenJDK repository of that technology, which includes the JVMs released from the AdoptOpenJDK project. Strictly speaking, the Oracle binaries require a license for production use, and the AdoptOpenJdK binaries come with an open source license. For our purposes, we’ll consider the two versions to be the same thing, which we’ll refer to as the JDK or the Java platform.1 These releases have gone through various bug fix releases. As I write this, the current version of Java 8 is jdk8u222 (version 222), and the current version of Java 11 is 11.0.5. It is important to use at least these versions (if not later), particularly in the case of Java 8. Early releases of Java 8 (through about jdk8u60) do not contain many of the important performance enhancements and features discussed throughout this book (particularly so with regard to garbage collection and the G1 garbage collector). These versions of the JDK were selected because they carry long-term support (LTS) from Oracle. The Java community is free to develop their own support models but so far have followed the Oracle model. So these releases will be supported and available for quite some time: through at least 2023 for Java 8 (via AdoptOpenJDK; later via extended Oracle support contracts), and through at least 2022 for Java 11. The next long-term release is expected to be in late 2021. For the interim releases, the discussion of Java 11 obviously includes features that were first made available in Java 9 or Java 10, even though those releases are unsup‐ ported both by Oracle and by the community at large. In fact, I’m somewhat impre‐ cise when discussing such features; it may seem that I’m saying features X and Y were originally included in Java 11 when they may have been available in Java 9 or 10. Java 11 is the first LTS release that carries those features, and that’s the important part: since Java 9 and 10 aren’t in use, it doesn’t really matter when the feature first appeared. Similarly, although Java 13 will be out at the time of this book’s release, there isn’t a lot of coverage of Java 12 or Java 13. You can use those releases in produc‐ tion, but only for six months, after which you’ll need to upgrade to a new release (so by the time you’re reading this, Java 12 is no longer supported, and if Java 13 is sup‐ ported, it will be soon replaced by Java 14). We’ll peek into a few features of these Platforms and Conventions | 3
interim releases, but since those releases are not likely to be put into production in most environments, the focus remains on Java 8 and 11. Other implementations of the Java Language specification are available, including forks of the open source implementation. AdoptOpenJDK supplies one of these (Eclipse OpenJ9), and others are available from other vendors. Although all these platforms must pass a compatibility test in order to be able to use the Java name, that compatibility does not always extend to the topics discussed in this book. This is par‐ ticularly true of tuning flags. All JVM implementations have one or more garbage col‐ lectors, but the flags to tune each vendor’s GC implementation are product-specific. Thus, while the concepts of this book apply to any Java implementation, the specific flags and recommendations apply only to the HotSpot JVM. That caveat is applicable to earlier releases of the HotSpot JVM—flags and their default values change from release to release. The flags discussed here are valid for Java 8 (specifically, version 222) and 11 (specifically, 11.0.5). Later releases could slightly change some of this information. Always consult the release notes for impor‐ tant changes. At an API level, different JVM implementations are much more compatible, though even then subtle differences might exist between the way a particular class is imple‐ mented in the Oracle HotSpot Java platform and an alternate platform. The classes must be functionally equivalent, but the actual implementation may change. Fortu‐ nately, that is infrequent, and unlikely to drastically affect performance. For the remainder of this book, the terms Java and JVM should be understood to refer specifically to the Oracle HotSpot implementation. Strictly speaking, saying “The JVM does not compile code upon first execution” is wrong; some Java imple‐ mentations do compile code the first time it is executed. But that shorthand is much easier than continuing to write (and read), “The Oracle HotSpot JVM…” JVM tuning flags With a few exceptions, the JVM accepts two kinds of flags: boolean flags, and flags that require a parameter. Boolean flags use this syntax: -XX:+FlagName enables the flag, and -XX:-FlagName disables the flag. Flags that require a parameter use this syntax: -XX:FlagName=something, meaning to set the value of FlagName to something. In the text, the value of the flag is usually ren‐ dered with something indicating an arbitrary value. For example, -XX:NewRatio=N means that the NewRatio flag can be set to an arbitrary value N (where the implica‐ tions of N are the focus of the discussion). 4 | Chapter 1: Introduction
The default value of each flag is discussed as the flag is introduced. That default is often based on a combination of factors: the platform on which the JVM is running and other command-line arguments to the JVM. When in doubt, “Basic VM Infor‐ mation” on page 60 shows how to use the -XX:+PrintFlagsFinal flag (by default, false) to determine the default value for a particular flag in a particular environ‐ ment, given a particular command line. The process of automatically tuning flags based on the environment is called ergonomics. The JVM that is downloaded from Oracle and AdoptOpenJDK sites is called the product build of the JVM. When the JVM is built from source code, many builds can be produced: debug builds, developer builds, and so on. These builds often have addi‐ tional functionality. In particular, developer builds include an even larger set of tun‐ ing flags so that developers can experiment with the most minute operations of various algorithms used by the JVM. Those flags are generally not considered in this book. Hardware Platforms When the first edition of this book was published, the hardware landscape looked dif‐ ferent than it does today. Multicore machines were popular, but 32-bit platforms and single-CPU platforms were still very much in use. Other platforms in use today—vir‐ tual machines and software containers—were coming into their own. Here’s an over‐ view of how those platforms affect the topics of this book. Multicore hardware Virtually all machines today have multiple cores of execution, which appear to the JVM (and to any other program) as multiple CPUs. Typically, each core is enabled for hyper-threading. Hyper-threading is the term that Intel prefers, though AMD (and others) use the term simultaneous multithreading, and some chip manufactures refer to hardware strands within a core. These are all the same thing, and we’ll refer to this technology as hyper-threading. From a performance perspective, the important thing about a machine is its number of cores. Let’s take a basic four-core machine: each core can (for the most part) pro‐ cess independently of the others, so a machine with four cores can achieve four times the throughput of a machine with a single core. (This depends on other factors about the software, of course.) In most cases, each core will contain two hardware or hyper-threads. These threads are not independent of each other: the core can run only one of them at a time. Often, the thread will stall: it will, for example, need to load a value from main memory, and that process can take a few cycles. In a core with a single thread, the thread stalls at that point, and those CPU cycles are wasted. In a core with two threads, the core can switch and execute instructions from the other thread. Platforms and Conventions | 5