74
Modern Java’s counter attack 자자자 자자자 자자 자자 자자자 자자자 자자자 자자자 자자자

모던자바의 역습

Embed Size (px)

Citation preview

Modern Java’s counter attack

자바를 둘러싼 진실 혹은 거짓말 그리고 과거와 미래에 대하여

김대우젬플레이 이사http://lekdw.blogspot.kr/

정도현 ( 정개발 )나는 프로그래머다 MC

일본 Mamezou 소속 컨설턴트http://Iamprogrammer.io

http://moreagile.net

새삼스런 자바 이야기

1 장

역사와 배경• 썬 마이크로시스템즈의 James Gosling, Mike Sheridan,

그리고 Patrick Naughton에 의해 인터렉티브 텔레비전을 개발하기 위해 개발된 언어• 처음엔 사무실 창밖에 있던 나무 이름을 따서 Oak 라고 하였으나

상표권 문제로 새 이름을 무작위로 찾다 발견한 단어가 Java 라는 설이 있음• 당시 절정의 인기를 구가하던 C/C++ 의 사용자를 흡수하기 위해

비슷한 문법을 채택• "Write Once, Run Anywhere” • 현실은 Write Once, Work Everywhere

https://en.wikipedia.org/wiki/Java_(programming_language)

자바의 목표• It must be "simple, object-oriented and familiar".• It must be "robust and secure".• It must be "architecture-neutral and portable".• It must execute with "high performance".• It must be "interpreted, threaded, and dynamic".

https://en.wikipedia.org/wiki/Java_(programming_language)

간단히 살펴보는 자바의 발자취• 1991 – Proejct Oak• 1995 – Alpha and Beta• 1996 – JDK 1.0• 1997 – JDK1.1• 1998 – J2SE 1.2• 2000 – J2SE1.3• 2002 – J2SE1.4

• 2004 – J2SE 5.0• 2006 – Java SE 6• 2011 – Java SE 7• 2014 – Java SE 8

https://en.wikipedia.org/wiki/Java_version_history

자바의 흑역사• 자바 씬크라이언트• 자바 OS

자바를 둘러싼 진실 혹은 거짓

2 장

자바는 미래는 어둡다

연도별 언어 인기도http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html

자바는 느리다

http://benchmarksgame.alioth.debian.org/u64/which-programs-are-fastest.html

NIO Direct Buffer + Memory Pool Algorithm

http://www3.ntu.edu.sg/home/ehchua/programming/java/j5b_io.html

http://www.evanjones.ca/software/java-bytebuffers.html

Netty PooledMemory

http://netty.io/wiki/using-as-a-generic-library.html

Terracotta BigMemory

http://terracotta.org/products/bigmemory

JVM Tuning

모바일 게임 서버와 같이 Life Cycle 이 짧은 데이터 ( 객체 ) 를 주로 처리하는 경우 , 별다른 튜닝없이 -server, -d64, -Xms, -Xmx 옵션으로 충분 .

더 빠른것을 원한다면• C/C++ 을 쓰자 !• 자바와 비슷한 문법• 풍부한 학습 리소스• 막강한 라이브러리

• POCO C++ Library• http://pocoproject.org/

• Apache Portable Runtime• https://apr.apache.org/

더 새롭고 편한것을 원한다면• JVM 언어를 활용하자 !• 라이브러리 레벨의 상호 호환성

• 주의할점 : JVM 언어들이 Java API 를 가져다 쓰기는 쉬워도 그 반대는 쉽지 않을 수 있음

• 높은 생산성을 원한다면• RoR 의 닮은꼴 : Grails - Groovy• Actor Model 을 이용한 고가용성 , 고확장성 어플리케이션 개발 : Play

- Scala

생산성이 구리다

언어별 생산성 비교

http://www.drdobbs.com/jvm/the-comparative-productivity-of-programm/240005881

Language Hours Per Function Point

ASP* 06.1

Visual Basic 08.5

Java 10.6

SQL 10.8

C++ 12.4

C 13.0

C# 15.5

PL/1 14.2

COBOL 16.8

ABAP 19.9

진실• C, C++ 과 비교해서 같은 시간이면 짧은 경력의 개발자라도 Java

가 좋은 품질의 코드 생산이 가능 .• 잘 발달된 정적 코드체크 시스템• 성능에 대한 한계점이 분명히 존재

• 문법적으로 행사코드가 많다• Java7 정도만 하더라도 충분히 모던언어와 비슷한 코딩이 가능• Java8 에 들어오면서 보다 많은부분 개선이 됨

코드 품질의 보증 – Code Analysis

• Checkstyle - Static analysis of coding conventions and standards.• Error Prone - Catches common Java mistakes as

compile-time errors.• FindBugs - Static analysis of bytecode to find potential

bugs.• PMD - Source code analysis of bad coding practices.• SonarQube - Integrates other analysis components via

plugins and provides an overview of the metrics over time.

풍부하고 고급진 High Level API 제공• Network : NIO• Concurrent Collection : ex)

ConcurrentHashMap(Bucket Lock)• More • https://github.com/akullpp/awesome-java

잘 정비된 개발환경

거대한 언어 생태계

http://readwrite.com/2011/01/24/the-java-ecosystem-infographic

자바의 인기 라이브러리들• JUnit⇑ 6474 - JUnit is a regression testing framework

written by Erich Gamma and Kent Beck. It is used by the developer who implements unit tests in Java.

• SLF4J API Module⇑ 3548 - The slf4j API• Scala Library⇑ 2976 - Standard library for the Scala

Programming Language• Logback Classic Module⇑ 1627 - logback-classic

module• Guava: Google Core Libraries for Java⇑ 1624 - Guava is

a suite of core and expanded libraries that include utility classes, google's collections, io classes, and much much more. Guava has only one code dependency - javax.annotation, per the JSR-305 spec.

• Mockito⇑ 1604 - Mock objects library for java• Google APIs Client Library for Java⇑ 1528• Apache Log4j⇑ 1466 - Apache Log4j 1.2• Commons IO⇑ 1424 - The Commons IO library contains

utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more.

• SLF4J LOG4J-12 Binding⇑ 1154 - SLF4J LOG4J-12 Binding

• osgi.core⇑ 1095 - OSGi Service Platform Release 4 Version 4.3, Core Interfaces and Classes for use in compiling bundles.

• JavaServlet(TM) Specification⇑ 1085• TestNG⇑ 1044 - TestNG is a testing framework.• ScalaTest⇑ 889 - ScalaTest is a free, open-source

testing toolkit for Scala and Java programmers.• Commons Lang⇑ 843 - Commons Lang, a

package of Java utility classes for the classes that are in java.lang's hierarchy, or are considered to be so standard as to justify existence in java.lang.

• Joda-Time⇑ 836 - Date and time library to replace JDK date handling

• Spring Context⇑ 771 - Spring Context• Mockito⇑ 771 - Mock objects library for java• H2 Database Engine⇑ 764 - H2 Database Engine• Java Servlet API⇑ 753

http://www.77dev.com/2014/05/java-trends-top-100-mostly-used.html

• JCL 1.1.1 implemented over SLF4J⇑ 729 - JCL 1.1.1 implemented over SLF4J

• jackson-databind⇑ 715 - General data-binding functionality for Jackson: works on core streaming API

• SLF4J Simple Binding⇑ 708 - SLF4J Simple binding• Apache Commons Codec⇑ 679 - The Apache

Commons Codec package contains simple encoder and decoders for various formats such as Base64 and Hexadecimal. In addition to these widely used encoders and decoders, the codec package also maintains a collection of phonetic encoding utilities.

• Apache HttpClient⇑ 615 - HttpComponents Client• Apache Commons Lang⇑ 615 - Apache Commons

Lang, a package of Java utility classes for the classes that are in java.lang's hierarchy, or are considered to be so standard as to justify existence in java.lang.

• Commons Logging⇑ 603 - Commons Logging is a thin adapter allowing configurable bridging to other, well known logging systems.

• Spring Core⇑ 599 - Spring Core• osgi.cmpn⇑ 590 - OSGi Compendium Release 5,

Interfaces and Classes for use in compiling bundles.• Google Guice - Core Library⇑ 536

• Spring TestContext Framework⇑ 532 - Spring TestContext Framework

• Jetty :: Server Core⇑ 501 - The core jetty server artifact.

• Maven Plugin API⇑ 497 - The API for plugins - Mojos - development.

• FindBugs-jsr305⇑ 492 - JSR305 Annotations for Findbugs

• Bean Validation API⇑ 473 - Bean Validation API• Spring Beans⇑ 472 - Spring Beans• Groovy⇑ 465 - Groovy: A powerful, dynamic

language for the JVM• Jackson-core⇑ 460 - Core Jackson abstractions,

basic JSON streaming API implementation• EasyMock⇑ 457 - EasyMock provides an easy way

to create Mock Objects for interfaces and classes generating them on the fly

• Spock Framework - Core Module⇑ 450 - Spock is a testing and specification framework for Java and Groovy applications. What makes it stand out from the crowd is its beautiful and highly expressive specification language. Thanks to its JUnit runner, Spock is compatible with most IDEs, build tools, and continuous integration servers. Spock is inspired from JUnit, jMock, RSpec, Groovy, Scala, Vulcans, and other fascinating life forms.

그리고 자바 8• Streams• Functional interfaces• Lambda• java.util.concurrent • Nashorn• New Date and Time• Akka with Java8

모던자바 Java8의 역습

3 장

Java coding style• C 스타일• Java 1.4 스타일• Effective Java 스타일• 스프링 스타일• Java8 스타일

일단은 Java7 부터

http://www.slideshare.net/shintanimoto/from-old-java-to-modern-java

private List m_list=null;private int process_file(String str_file_name){ String str_line; List list_lines=new ArrayList(); int i_result=read_file(str_file_name,list_lines); if(i_result==0){ List list_record=new ArrayList(); for(int i=0;i<list_lines.size();i++){ str_line=(String)list_lines.get(i); Record record=new Record(); i_result=parse_line(str_line,record); if(i_result!=0){ return i_result; } list_recordord.add(record); } m_list=list_record; return 0; }else{ return i_result; }}

http://www.slideshare.net/shintanimoto/from-old-java-to-modern-java

C-ish java

private List resultList;private List processFile(String fileName)throws SystemException { List lines = readFile(fileName); List recordList = new ArrayList(); for (int i = 0; i < lines.size(); i++) { String line = (String) lines.get(i); Record record = parseLine(line); recordList.add(record); } return recordList;}

http://www.slideshare.net/shintanimoto/from-old-java-to-modern-java

Java 1.4

private List<Record> processFile(String fileName)throws SystemException { List<String> lines = readFile(fileName); List<Record> recordList = new ArrayList(); for (String line : lines) { Record record = parseLine(line); recordList.add(record); } return recordList;}

Java 1.7 generic + foreach

try-with-resources

private List<String> readFile(String fileName) { List<String> lines = new ArrayList<String>(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(fileName)); String line; while ((line = reader.readLine()) != null) { lines.add(line); } } catch (FileNotFoundException ex) { throw new SystemException(FILE_NOT_FOUND, ex); } catch (IOException ex) { throw new SystemException(FILE_READ_ERROR, ex); } finally { try { if (reader != null) { reader.close(); } } catch (IOException ex) { // 이건 무시 ? } } return lines;}

private List<String> readFile(String fileName) { List<String> lines = new ArrayList<>(); try (FileReader in = new FileReader(fileName); BufferedReader reader = new BufferedReader(in)) { String line; while ((line = reader.readLine()) != null) { lines.add(line); } } catch (FileNotFoundException ex) { throw new SystemException(FILE_NOT_FOUND, ex); } catch (IOException ex) { throw new SystemException(FILE_READ_ERROR, ex); } return lines;}

Java 7

private List<String> readFile(String fileName) { try { return Files.readAllLines(Paths.get(fileName), Charset.defaultCharset()); } catch (IOException ex) { throw new SystemException(FILE_READ_ERROR, ex); }}

Java 7

함수형 프로그래밍 패러다임• 순수한 함수• Thread safe, 병렬계산 가능

• 익명 함수• 고계 함수

https://ko.wikipedia.org/wiki/ 함수형 _프로그래밍

Quick Sort

public static <E extends Comparable<? super E>> List<E> quickSort(List<E> arr) { if (!arr.isEmpty()) { E pivot = arr.get(0); //This pivot can change to get faster results List<E> less = new LinkedList<E>(); List<E> pivotList = new LinkedList<E>(); List<E> more = new LinkedList<E>(); for (E i: arr) { if (i.compareTo(pivot) < 0) less.add(i); else if (i.compareTo(pivot) > 0) more.add(i); else pivotList.add(i); } less = quickSort(less); more = quickSort(more); less.addAll(pivotList); less.addAll(more); return less; } return arr;}

http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Java

Java 7

public static <T> List<T> Quicksort(List<T> v, BiFunction<T, T, Integer> comparer) { if (v.size() < 2) return v; T pivot = v.get(v.size() / 2); List<T> l = new LinkedList<T>(Quicksort(v.stream() .filter(x -> comparer.apply(x, pivot) < 0) .collect(Collectors.toList()), comparer)); l.addAll( v.stream().filter(x -> comparer .apply(x, pivot) == 0).collect(Collectors.toList()) ); l.addAll( Quicksort(v.stream() .filter(x -> comparer.apply(x, pivot) > 0) .collect(Collectors.toList()), comparer) ); return l;}

Java 8

qsort [] = [] qsort (x:xs) = qsort (filter (< x) xs) ++ [x] ++ qsort (filter (>= x) xs)

https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Quicksort#Haskell

Haskell

Streams

package org.ingini.spark.java8; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.TreeMap; import static java.util.function.Function.identity; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; public class WordsCounterJava { public static final String REGEX = "\\s+"; public TreeMap<String, Long> count(String source) throws IOException { return Files.lines(Paths.get(source)) .map(line -> line.split(REGEX)) .flatMap(Arrays::stream) .collect(groupingBy(identity(), TreeMap::new, counting())); }}

-Djava.util.concurrent.ForkJoinPool.common.parallelism=1

SELECT * FROM BOOK WHERE BOOK.PUBLISHED_IN = 2011 ORDER BY BOOK.TITLE

jOOQ

create.selectFrom(BOOK) .where(BOOK.PUBLISHED_IN.eq(2011)) .orderBy(BOOK.TITLE)

http://www.jooq.org/

Functional interfaces & Lambda

http://java2practice.com/2014/03/16/java-8-functional-interface-example/

Thread t =new Thread(new Runnable(){   public void run(){     System.out.println("Runnable implemented by using Lambda Expression");   }});

Thread t = new Thread(()->{   System.out.println("Runnable implemented by using Lambda Expression");});

Java 7

Java 8

interface DefaultInterfaceTest{  void show();  default void display(){     System.out.println("Default method from interface can have body..!");  }}public class DefaultInterfaceTestImpl implements DefaultInterfaceTest{   public void show(){         System.out.println("show method");   }   //we dont need to provide any implementation to default method.   public static void main(String[] args){          DefaultInterfaceTest obj = new DefaultInterfaceTestImpl();          obj.show();//out puts: show method          obj.display();//outputs : Default method from interface can have body..!        }}

Default Method

java.util.function

•Function <T, R> - T 를 입력으로 R 을 출력으로 반환•Predicate <T> - T 를 입력으로 boolean 을 출력으로 반환•Consumer <T> - T 를 입력으로 아무것도 반환하지 않는다•Supplier <T> - 입력을 취하지 않고 T 를 반환•BinaryOperator <T> - 2 개의 T 를 입력으로 하나의 T 를 출력으로 반환

java.util.concurrent

http://www.ibm.com/developerworks/library/j-jvmc2/index.html

Runnable task = () -> { String threadName = Thread.currentThread().getName(); System.out.println("Hello " + threadName); };

task.run();

Thread thread = new Thread(task); thread.start();

ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> { String threadName = Thread.currentThread().getName(); System.out.println("Hello " + threadName); }); try { //attempt to shutdown executor executor.shutdown(); executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { System.err.println("tasks interrupted"); } finally { if (!executor.isTerminated()) { executor.shutdownNow(); } System.out.println("shutdown finished"); }

Executors

http://winterbe.com/posts/2015/04/07/java8-concurrency-tutorial-thread-executor-examples/

Nashorn vs V8

http://ariya.ofilabs.com/2014/03/nashorn-the-new-rhino-on-the-block.html

Spring with Java8

interface CustomerRepository extends Repository<Customer, Long> { @Query("select c from Customer c") Stream<Customer> streamAllCustomers();}

try (Stream<Customer> customers = repository.streamAllCustomers()) { // use the stream here }

Support for JDK 8' Stream in repository methods

CompletableFuture in @Asnycinterface CustomerRepository extends Repository<Customer, Long> {

@Async CompletableFuture<List<Customer>> readAllBy(); }

CompletableFuture<List<Customer>> future = repository.readAllBy().thenApply(this::doSomethingWithCustomers);

while (!future.isDone()) { log.info("Waiting for the CompletableFuture to finish..."); TimeUnit.MILLISECONDS.sleep(500);}

List<Customer> processedCustomers = future.get();

Akka with Java8

http://doc.akka.io/docs/akka/2.3.0-RC1/java/lambda-actors.html

import akka.actor.AbstractActor;import akka.event.Logging;import akka.event.LoggingAdapter;import akka.japi.pf.ReceiveBuilder;import scala.PartialFunction;import scala.runtime.BoxedUnit; public class MyActor extends AbstractActor { private final LoggingAdapter log = Logging.getLogger(context().system(), this);  @Override public PartialFunction<Object, BoxedUnit> receive() { return ReceiveBuilder. match(String.class, s -> s.equals("test"), s -> log.info("received test")). matchAny(o -> log.info("received unknown message")).build(); }}

고통없는 자바 8 도입• 시기적인 문제점• 안정화 및 라이브러리 지원

• OpenJDK 8 공개 : 2012 년 4 월 - 대부분의 라이브러리들이 지원완료• 새로운 문법에 익숙해 지기

• 몹 프로그래밍• 코드리뷰• 사내 워크샵• 온라인 교육

• 7 월 14 일부터 오라클에서 람다와 스트림에 대한 온라인 코스 개시• https://

blogs.oracle.com/javatraining/entry/announcing_jdk_8_mooc_lambdas

함수형 프로그래밍 패러다임

결론4 장

불멸의 고전게임 스트리트파이터 2

개성이 강한 8 명의 깡패격투가

달심 - 느리다 , 멋이 없다 , 재미 없다

화려한 필살기나 스피드는 없지만

착실한 1 승을 위한 최선의 선택

잘 키운 딸 하나 열 아들 안부럽다잘 키운 달심하나 일곱전사 안부럽다

잘 키운 자바 하나 일곱 언어 안부럽다

자바 8 의 장점들• 함수형 프로그래밍 패러다임 지원• 보다 간결해진 문법• 잘만 쓰면 groovy 나 스칼라 안부럽다

• 주요 라이브러리들의 자바 8 지원 완료• 잘 정비된 개발환경• 20 년간 조성되어 온 거대한 생태계

단점을 커버하는 방법• 보다 높은 생산성과 함수형 프로그래밍을 원한다면 -> JVM 언어들• 스칼라 , 클로져 , 그루비 , JRuby, JPython 그리고 JVM 의 Swift –

Kotlin• 자바와의 API 레벨 상호 호환성

• 단 , 자바 API 를 부르기는 쉬워도 다른 JVM 언어 API 를 자바에서 부르기는 불편함

• 보다 빠른 성능을 원한다면• C/C++

감사합니다