M A N N I N G Benjamin J. Evans Martijn Verburg FOREWORD BY Dr. Heinz Kabutz Vital techniques of Java 7 and polyglot programming The
RULES OF THE JAVA MEMORY MODEL Example of Synchronizes-With JMM has the following rules: ■ An unlock operation on a monitor Synchronizes-With later lock operations ■ A write to a volatile variable Synchronizes-With later reads of the variable ■ If an action A Synchronizes-With action B, then A Happens-Before B ■ If A comes before B in program order within a thread, then A Happens-Before B Read more in chapter 4.
The Well-Grounded Java Developer
(This page has no text content)
The Well-Grounded Java Developer VITAL TECHNIQUES OF JAVA 7 AND POLYGLOT PROGRAMMING BENJAMIN J. EVANS MARTIJN VERBURG M A N N I N G SHELTER ISLAND
For online information and ordering of this and other Manning books, please visit www.manning.com. The publisher offers discounts on this book when ordered in quantity. For more information, please contact Special Sales Department Manning Publications Co. 20 Baldwin Road PO Box 261 Shelter Island, NY 11964 Email: orders@manning.com ©2013 by Manning Publications Co. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by means electronic, mechanical, photocopying, or otherwise, without prior written permission of the publisher. Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those designations appear in the book, and Manning Publications was aware of a trademark claim, the designations have been printed in initial caps or all caps. Recognizing the importance of preserving what has been written, it is Manning’s policy to have the books we publish printed on acid-free paper, and we exert our best efforts to that end. Recognizing also our responsibility to conserve the resources of our planet, Manning books are printed on paper that is at least 15 percent recycled and processed without the use of elemental chlorine. Manning Publications Co. Development editors: Renae Gregoire, Karen G. Miller 20 Baldwin Road Copyeditor: Andy Carroll PO Box 261 Proofreader: Elizabeth Martin Shelter Island, NY 11964 Typesetter: Dennis Dalinnik Cover designer: Marija Tudor ISBN: 9781617290060 Printed in the United States of America 1 2 3 4 5 6 7 8 9 10 – MAL – 18 17 16 15 14 13 12
brief contents PART 1 DEVELOPING WITH JAVA 7 .............................................1 1 ■ Introducing Java 7 3 2 ■ New I/O 20 PART 2 VITAL TECHNIQUES .....................................................51 3 ■ Dependency Injection 53 4 ■ Modern concurrency 76 5 ■ Class files and bytecode 119 6 ■ Understanding performance tuning 150 PART 3 POLYGLOT PROGRAMMING ON THE JVM....................191 7 ■ Alternative JVM languages 193 8 ■ Groovy: Java’s dynamic friend 213 9 ■ Scala: powerful and concise 241 10 ■ Clojure: safer programming 279 PART 4 CRAFTING THE POLYGLOT PROJECT ...........................311 11 ■ Test-driven development 313 12 ■ Build and continuous integration 342 13 ■ Rapid web development 380v 14 ■ Staying well-grounded 410
(This page has no text content)
contents foreword xvii preface xix acknowledgments xxi about this book xxiv about the authors xxix about the cover illustration xxx PART 1 DEVELOPING WITH JAVA 7..................................1 1 Introducing Java 7 3 1.1 The language and the platform 4 1.2 Small is beautiful—Project Coin 5 1.3 The changes in Project Coin 9 Strings in switch 9 ■ Enhanced syntax for numeric literals 10 ■ Improved exception handling 12 Try-with-resources (TWR) 13 ■ Diamond syntax 16 Simplified varargs method invocation 17 1.4 Summary 19 2 New I/O 20 2.1 Java I/O—a history 22 Java 1.0 to 1.3 22 ■ Java 1.4 and NIO 23vii Introducing NIO.2 24
CONTENTSviii 2.2 Path—a foundation of file-based I/O 24 Creating a Path 27 ■ Retrieving information from a Path 27 Removing redundancies 28 ■ Converting Paths 29 NIO.2 Path and Java’s existing File class 30 2.3 Dealing with directories and directory trees 30 Finding files in a directory 30 ■ Walking the directory tree 31 2.4 Filesystem I/O with NIO.2 33 Creating and deleting files 34 ■ Copying and moving files 35 File attributes 36 ■ Reading and writing data quickly 40 File change notification 41 ■ SeekableByteChannel 42 2.5 Asynchronous I/O operations 43 Future style 44 ■ Callback style 46 2.6 Tidying up Socket-Channel functionality 47 NetworkChannel 48 ■ MulticastChannel 49 2.7 Summary 50 PART 2 VITAL TECHNIQUES .........................................51 3 Dependency Injection 53 3.1 Inject some knowledge—understanding IoC and DI 54 Inversion of Control 54 ■ Dependency Injection 55 Transitioning to DI 56 3.2 Standardized DI in Java 61 The @Inject annotation 62 ■ The @Qualifier annotation 64 The @Named annotation 65 ■ The @Scope annotation 65 The @Singleton annotation 66 ■ The Provider<T> interface 66 3.3 Guice 3—the reference implementation for DI in Java 67 Getting started with Guice 68 ■ Sailor’s knots—the various bindings of Guice 70 ■ Scoping your injected objects with Guice 73 3.4 Summary 75 4 Modern concurrency 76 4.1 Concurrency theory—a primer 77 Explaining Java’s threading model 77 ■ Design concepts 79 How and why do the forces conflict? 80 ■ Sources of overhead 81 A transaction processor example 81
CONTENTS ix 4.2 Block-structured concurrency (pre-Java 5) 83 Synchronization and locks 83 ■ The state model for a thread 84 Fully synchronized objects 85 ■ Deadlocks 86 Why synchronized? 88 ■ The volatile keyword 89 Immutability 90 4.3 Building blocks for modern concurrent applications 91 Atomic classes—java.util.concurrent.atomic 92 Locks—java.util.concurrent.locks 93 ■ CountDownLatch 96 ConcurrentHashMap 97 ■ CopyOnWriteArrayList 99 Queues 102 4.4 Controlling execution 108 Modeling tasks 108 ■ ScheduledThreadPoolExecutor 110 4.5 The fork/join framework 111 A simple fork/join example 112 ■ ForkJoinTask and work stealing 114 ■ Parallelizing problems 115 4.6 The Java Memory Model (JMM) 116 4.7 Summary 118 5 Class files and bytecode 119 5.1 Classloading and class objects 120 Overview—loading and linking 120 ■ Verification 121 Class objects 122 ■ Classloaders 122 ■ Example—classloaders in Dependency Injection 124 5.2 Using method handles 125 MethodHandle 126 ■ MethodType 127 ■ Looking up method handles 127 ■ Example—reflection vs. proxies vs. MethodHandles 128 ■ Why choose MethodHandles? 131 5.3 Examining class files 132 Introducing javap 132 ■ Internal form for method signatures 132 ■ The constant pool 134 5.4 Bytecode 136 Example—disassembling a class 137 ■ The runtime environment 138 ■ Introduction to opcodes 140 Load and store opcodes 141 ■ Arithmetic opcodes 141 Execution control opcodes 142 ■ Invocation opcodes 143 Platform operation opcodes 143 ■ Shortcut opcode forms 144 Example—string concatenation 144
CONTENTSx 5.5 Invokedynamic 146 How invokedynamic works 146 ■ Example—disassembling an invokedynamic call 147 5.6 Summary 149 6 Understanding performance tuning 150 6.1 Performance terminology—some basic definitions 152 Latency 152 ■ Throughput 152 ■ Utilization 153 Efficiency 153 ■ Capacity 153 ■ Scalability 154 Degradation 154 6.2 A pragmatic approach to performance analysis 154 Know what you’re measuring 155 ■ Know how to take measurements 156 ■ Know what your performance goals are 157 ■ Know when to stop optimizing 157 Know the cost of higher performance 158 ■ Know the danger of premature optimization 158 6.3 What went wrong? Why we have to care 159 Moore’s Law—historic and future performance trends 160 Understanding the memory latency hierarchy 161 ■ Why is Java performance tuning hard? 162 6.4 A question of time—from the hardware up 163 Hardware clocks 163 ■ The trouble with nanoTime() 164 The role of time in performance tuning 166 ■ A case study— understanding cache misses 167 6.5 Garbage collection 169 Basics 170 ■ Mark and sweep 170 ■ jmap 172 Useful JVM parameters 176 ■ Reading the GC logs 177 Visualizing memory usage with VisualVM 178 Escape analysis 181 ■ Concurrent Mark-Sweep 182 G1—Java’s new collector 183 6.6 JIT compilation with HotSpot 184 Introduction to HotSpot 186 ■ Inlining methods 187 Dynamic compilation and monomorphic calls 188 Reading the compilation logs 188 6.7 Summary 190
CONTENTS xi PART 3 POLYGLOT PROGRAMMING ON THE JVM ........191 7 Alternative JVM languages 193 7.1 Java too clumsy? Them’s fighting words! 194 The reconciliation system 194 ■ Conceptual basics of functional programming 196 ■ Map and filter idioms 197 7.2 Language zoology 198 Interpreted vs. compiled languages 199 ■ Dynamic vs. static typing 199 ■ Imperative vs. functional languages 200 Reimplementation vs. original 201 7.3 Polyglot programming on the JVM 202 Why use a non-Java language? 203 Up-and-coming languages 204 7.4 How to choose a non-Java language for your project 205 Is the project area low-risk? 205 ■ Does the language interoperate well with Java? 206 ■ Is there good tooling and test support for the language? 207 ■ How hard is the language to learn? 207 Are there lots of developers using this language? 208 7.5 How the JVM supports alternative languages 208 Runtime environments for non-Java languages 209 Compiler fictions 209 7.6 Summary 211 8 Groovy: Java’s dynamic friend 213 8.1 Getting started with Groovy 215 Compiling and running 216 ■ Groovy console 217 8.2 Groovy 101—syntax and semantics 217 Default imports 219 ■ Numeric handling 219 Variables, dynamic versus static types, and scoping 220 Syntax for lists and maps 222 8.3 Differences from Java—traps for new players 223 Optional semicolons and return statements 224 Optional parentheses for method parameters 224 Access modifiers 225 ■ Exception handling 225 Equality in Groovy 225 ■ Inner classes 226 8.4 Groovy features not (yet) in Java 226 GroovyBeans 227 ■ The safe-dereference operator 228 The Elvis operator 228 ■ Enhanced strings 229
CONTENTSxii Function literals 230 ■ First-class support for manipulating collections 231 ■ First-class support for regular expressions 233 ■ Simple XML handling 234 8.5 Interoperating between Groovy and Java 236 Calling Java from Groovy 236 ■ Calling Groovy from Java 237 8.6 Summary 240 9 Scala: powerful and concise 241 9.1 A quick tour of Scala 242 Scala as a concise language 243 ■ Match expressions 245 Case classes 247 ■ Actors 248 9.2 Is Scala right for my project? 249 Comparing Scala and Java 250 ■ When and how to start using Scala 250 ■ Signs that Scala may not be right for your current project 251 9.3 Making code beautiful again with Scala 251 Using the compiler and the REPL 252 ■ Type inference 252 Methods 254 ■ Imports 255 ■ Loops and control structures 256 ■ Functional programming in Scala 257 9.4 Scala’s object model—similar but different 258 Everything is an object 258 ■ Constructors 259 ■ Traits 260 Singleton and companion objects 262 ■ Case classes and match expressions 264 ■ A cautionary tale 266 9.5 Data structures and collections 267 List 268 ■ Map 271 ■ Generic types 272 9.6 Introduction to actors 275 All the code’s a stage 276 ■ Communicating with actors via the mailbox 276 9.7 Summary 278 10 Clojure: safer programming 279 10.1 Introducing Clojure 280 Hello World in Clojure 281 ■ Getting started with the REPL 281 ■ Making a mistake 282 Learning to love the brackets 283 10.2 Looking for Clojure—syntax and semantics 284 Special forms bootcamp 284 ■ Lists, vectors, maps, and sets 285 Arithmetic, equality, and other operations 287
CONTENTS xiii 10.3 Working with functions and loops in Clojure 288 Some simple Clojure functions 289 ■ Loops in Clojure 291 Reader macros and dispatch 292 ■ Functional programming and closures 293 10.4 Introducing Clojure sequences 295 Lazy sequences 297 ■ Sequences and variable-arity functions 298 10.5 Interoperating between Clojure and Java 299 Calling Java from Clojure 299 ■ The Java type of Clojure values 300 ■ Using Clojure proxies 301 Exploratory programming with the REPL 302 Using Clojure from Java 302 10.6 Concurrent Clojure 303 Futures and pcalls 304 ■ Refs 306 ■ Agents 309 10.7 Summary 310 PART 4 CRAFTING THE POLYGLOT PROJECT ...............311 11 Test-driven development 313 11.1 TDD in a nutshell 315 A TDD example with a single use case 316 ■ A TDD example with multiple use cases 320 ■ Further thinking on the red-green-refactor lifecycle 322 ■ JUnit 324 11.2 Test doubles 325 Dummy object 326 ■ Stub object 328 ■ Fake object 331 Mock object 336 11.3 Introducing ScalaTest 338 11.4 Summary 340 12 Build and continuous integration 342 12.1 Getting started with Maven 3 345 12.2 Maven 3—a quick-start project 346 12.3 Maven 3—the Java7developer build 348 The POM 348 ■ Running the examples 354 12.4 Jenkins—serving your CI needs 357 Basic configuration 359 ■ Setting up a job 360 Executing a job 364
CONTENTSxiv 12.5 Code metrics with Maven and Jenkins 365 Installing Jenkins plugins 366 ■ Making code consistent with Checkstyle 367 ■ Setting the quality bar with FindBugs 369 12.6 Leiningen 372 Getting started with Leiningen 372 ■ Leiningen’s architecture 373 ■ Example—Hello Lein 373 REPL-oriented TDD with Leiningen 376 Packaging and deploying with Leiningen 377 12.7 Summary 379 13 Rapid web development 380 13.1 The problem with Java-based web frameworks 381 Why Java compilation is bad for rapid web development 382 Why static typing is bad for rapid web development 383 13.2 Criteria in selecting a web framework 383 13.3 Getting started with Grails 385 13.4 Grails quick-start project 386 Domain object creation 387 ■ Test-driven development 388 Domain object persistence 390 ■ Test data creation 391 Controllers 392 ■ GSP/JSP views 393 Scaffolding and automatic UI creation 395 Rapid turnaround development 395 13.5 Further Grails exploration 396 Logging 396 ■ GORM—object-relational mapping 397 Grails plugins 398 13.6 Getting started with Compojure 399 Hello World with Compojure 399 ■ Ring and routes 401 Hiccup 402 13.7 A sample Compojure project—“Am I an Otter or Not?” 403 Setting up “Am I an Otter” 404 ■ Core functions in “Am I an Otter” 406 13.8 Summary 409 14 Staying well-grounded 410 14.1 What to expect in Java 8 411 Lambdas (a.k.a. closures) 411 Modularization (a.k.a. Jigsaw) 413
CONTENTS xv 14.2 Polyglot programming 414 Language interoperability and metaobject protocols 415 Multilanguage modularity 416 14.3 Future concurrency trends 416 The many-core world 417 ■ Runtime-managed concurrency 417 14.4 New directions in the JVM 418 VM convergence 418 ■ Coroutines 419 ■ Tuples 421 14.5 Summary 423 appendix A Java7developer—source code installation 424 appendix B Glob pattern syntax and examples 432 appendix C Installing alternative JVM languages 434 appendix D Downloading and installing Jenkins 441 appendix E Java7developer—the Maven POM 444 index 450
(This page has no text content)
foreword “Kirk told me I could buy beer at the petrol station,” was the first sentence I heard out of Ben Evans’ mouth. He had come to Crete for an Open Spaces Java conference. I explained that I usually bought petrol at the petrol station, but that there was a shop around the corner that sold beer. Ben looked disappointed. I had lived on this Greek island for five years and had never thought of trying to buy beer at the local BP. I felt a bit like this while reading this book. I consider myself a Java fundi. I have spent the past 15 years programming Java, writing hundreds of articles, speaking at conferences, and teaching advanced Java courses. And yet, when I read Ben and Martijn’s book, I kept coming across ideas that I hadn’t thought of. They start by explaining the development effort of changing certain parts of the Java ecosystem. Changing the internals of a library is relatively easy, and we might see some improved performance for certain input. Arrays.sort() is now using TimSort, instead of MergeSort. If you sort a partially ordered array, you might see a slight per- formance improvement without changing your code. Changing the class file format or adding a new VM feature requires a major effort. Ben knows. He sits on the JCP Executive Committee. This book is also about Java 7, so you’ll learn all the new fea- tures, such as the syntactic sugar enhancements, switching on Strings, fork/join, and the Java NIO.2. Concurrency? That’s Thread and synchronized, right? If that’s all you know about multithreading, it’s time to upgrade your skills. As the authors point out, “the area of concurrency is undergoing a massive amount of research at present.” There are daily discussions on the concurrency interest mailing list, and new ideas are emerging allxvii
FOREWORDxviii the time. This book shows you how to think about divide-and-conquer and how to avoid some of the safety flaws. When I saw the chapter on classloading, I thought they had gone a bit too far. Here were the tricks that my friends and I had used to create magical code, laid bare for all to learn! They explain how javap works, a little tool that can give you insight into the byte- code generated by the Java compiler. They also cover the new invokedynamic and explain how it differs from plain reflection. One chapter that I particularly like is “Understanding performance tuning.” This is the first book since Jack Shirazi’s Java Performance Tuning that has captured the essence of how to make your system faster. I can summarize the chapter in three words: “Measure, don’t guess.” This is the essence of good performance tuning. It’s impossible for a human to guess which code is slow. Instead of offering a single coding trick, this chapter explains performance from a hardware perspective. It also shows you how to measure the performance. An interesting little benchmark tool is their CacheTester class, which shows the cost of cache misses. Part 3 of the book explains polyglot programming on the JVM. Java is so much more than a Java programming language. It’s also a platform on which other languages can run. We’ve seen an explosion of different types of languages. Some are functional, some are declarative. Some are ports (Jython and JRuby), allowing other languages to run on the JVM. Languages can be dynamic (Groovy) or stable (Java and Scala). There are many reasons to use a non-Java language on the JVM. If you’re starting a new project, look at what’s available before deciding. You might save yourself a lot of boilerplate code. Ben and Martijn show us three alternative languages: Groovy, Scala, and Clojure. In my opinion, these are the most viable languages at the moment. The authors describe the differences between these languages, how they compare to Java, and their special features. The chapter on each language is just enough to help you figure out which you should be using, without too much technical detail. Don’t expect a reference manual to Groovy; do expect insight on which language is the right one for you. Next, you’ll gain insight into how to do test-driven development and continuous integration of your system. I found it amusing that the old faithful butler Hudson was so quickly replaced with Jenkins. In any case, these are essential tools for managing your project, along with tools like Checkstyle and FindBugs. Studying this book will help you become a well-grounded Java developer. Not only that, it will give you tips on how to stay well-grounded. Java is constantly changing. We’ll see lambdas and modularization in the next version. New languages are being designed; the concurrency constructs are being updated. Many of the things that you know are true now might not be true in the future. The lesson is, don’t ever stop learning! The other day I drove past the petrol station where Ben wanted to buy his beer. Like so many companies in depressed Greece, it had closed. I never did find out if they sold beer. DR. HEINZ KABUTZTHE JAVA SPECIALISTS’ NEWSLETTER
Comments 0
Loading comments...
Reply to Comment
Edit Comment