001. foreword
002. Part 1. From 8 to 11 and beyond!
003. Chapter 1. Introducing modern Java
004. Chapter 1. The new Java release model
005. Chapter 1. Enhanced type inference (var keyword)
006. Chapter 1. Changing the language and the platform
007. Chapter 1. Small changes in Java 11
008. Chapter 1. HTTP2 (Java 11)
009. Chapter 2. Java modules
010. Chapter 2. The module graph
011. Chapter 2. Basic modules syntax
012. Chapter 2. Loading modules
013. Chapter 2. Building a first modular app
014. Chapter 2. Architecting for modules
015. Chapter 2. Multi-release JARs
016. Chapter 3. Java 17
017. Chapter 3. Records
018. Chapter 3. Nominal typing
019. Chapter 3. Sealed Types
020. Chapter 3. New form of instanceof
021. Part 2. Under the hood
022. Chapter 4. Class files and bytecode
023. Chapter 4. Class objects
024. Chapter 4. Custom class loading
025. Chapter 4. Examining class files
026. Chapter 4. Disassembling a class
027. Chapter 4. Introduction to opcodes
028. Chapter 4. Invocation opcodes
029. Chapter 4. Reflection
030. Chapter 5. Java concurrency fundamentals
031. Chapter 5. Amdahls law
032. Chapter 5. Design concepts
033. Chapter 5. Block-structured concurrency (pre-Java 5)
034. Chapter 5. Deadlocks
035. Chapter 5. Thread states and methods
036. Chapter 5. Immutability
037. Chapter 5. Understanding concurrency through bytecode
038. Chapter 5. Unsynchronized reads
039. Chapter 6. JDK concurrency libraries
040. Chapter 6. CountDownLatch
041. Chapter 6. Approaches to a concurrent Dictionary
042. Chapter 6. CopyOnWriteArrayList
043. Chapter 6. Using BlockingQueue APIs
044. Chapter 6. CompletableFuture
045. Chapter 6. Single-threaded executor
046. Chapter 7. Understanding Java performance
047. Chapter 7. A pragmatic approach to performance analysis
048. Chapter 7. Know what your performance goals are
049. Chapter 7. What went wrong Why do we have to care
050. Chapter 7. Why is Java performance tuning hard
051. Chapter 7. Garbage collection
052. Chapter 7. Young collections
053. Chapter 7. The Parallel collector
054. Chapter 7. JIT compilation with HotSpot
055. Chapter 7. Inlining methods
056. Chapter 7. JDK Flight Recorder
057. Part 3. Non-Java languages on the JVM
058. Chapter 8. Alternative JVM languages
059. Chapter 8. Imperative vs. functional languages
060. Chapter 8. Polyglot programming on the JVM
061. Chapter 8. Up-and-coming languages
062. Chapter 8. How to choose a non-Java language for your project
063. Chapter 8. How the JVM supports alternative languages
064. Chapter 9. Kotlin
065. Chapter 9. Functions
066. Chapter 9. Collections
067. Chapter 9. A different view of classes and objects
068. Chapter 9. Safety
069. Chapter 9. Concurrency
070. Chapter 10. Clojure A different view of programming
071. Chapter 10. Getting started with the REPL
072. Chapter 10. Looking for Clojure Syntax and semantics
073. Chapter 10. Arithmetic, equality, and other operations
074. Chapter 10. Loops in Clojure
075. Chapter 10. Functional programming and closures
076. Chapter 10. Interoperating between Clojure and Java
077. Chapter 10. Macros
078. Part 4. Build and deployment
079. Chapter 11. Building with Gradle and Maven
080. Chapter 11. Ensuring consistency between developers
081. Chapter 11. Controlling the manifest
082. Chapter 11. Dependency management
083. Chapter 11. Maven and modules
084. Chapter 11. Gradle
085. Chapter 11. Dependencies in Gradle
086. Chapter 11. Testing
087. Chapter 11. Using Gradle with modules
088. Chapter 12. Running Java in containers
089. Chapter 12. Host operating systems vs. virtual machines vs. containers
090. Chapter 12. Docker fundamentals
091. Chapter 12. Developing Java applications with Docker
092. Chapter 12. Ports and hosts
093. Chapter 12. Debugging in Docker
094. Chapter 12. Kubernetes
095. Chapter 12. Observability and performance
096. Chapter 12. Performance in containers
097. Chapter 13. Testing fundamentals
098. Chapter 13. Test-driven development
099. Chapter 13. A TDD example with a single use case
100. Chapter 13. Test doubles
101. Chapter 13. Fake object
102. Chapter 13. From JUnit 4 to 5
103. Chapter 14. Testing beyond JUnit
104. Chapter 14. Gathering container logs
105. Chapter 14. Specification-style testing with Spek and Kotlin
106. Chapter 14. Property-based testing with Clojure
107. Chapter 14. test.check
108. Part 5. Java frontiers
109. Chapter 15. Advanced functional programming
110. Chapter 15. Recursion
111. Chapter 15. Limitations of Java as a FP language
112. Chapter 15. Recursion
113. Chapter 15. Laziness
114. Chapter 15. Kotlin FP
115. Chapter 15. Tail recursion
116. Chapter 15. Sequences
117. Chapter 15. Lazy sequences
118. Chapter 16. Advanced concurrent programming
119. Chapter 16. Concurrency and functional programming
120. Chapter 16. Under the hood with Kotlin coroutines
121. Chapter 16. Concurrent Clojure
122. Chapter 16. Software transactional memory
123. Chapter 17. Modern internals
124. Chapter 17. Final methods
125. Chapter 17. MethodType
126. Chapter 17. Invokedynamic
127. Chapter 17. Small internal changes
128. Chapter 17. Unsafe
129. Chapter 17. Replacing Unsafe with supported APIs
130. Chapter 18. Future Java
131. Chapter 18. Project Panama
132. Chapter 18. Project Loom
133. Chapter 18. Thread builders
134. Chapter 18. Project Valhalla
135. Chapter 18. Consequences of value objects
136. Chapter 18. Generics revisited
137. Appendix A. Selecting your Java