Java 8 Tutorial: Trọn bộ Java 8 new features từ Pluralsight

Giới thiệu

Blog_Green-Board

Hôm nay mình sẽ share một bộ video Trọn bộ Java 8 new features từ Pluralsight . Với hơn 4 giờ học, các bạn sẽ nắm được tất cả những đặc điểm nổi bật nhất trong Java 8 như Lambda Expression, Stream, Date and Time API, …

This course covers the most useful parts of Java 8. This update of the Java platform is the biggest of all. It’s even bigger than Java 5 that saw the introduction of generics. We’ll begin with lambda expressions and the Stream API, which bring new fundamental patterns to the Java platform. Many problems solved with the Iterator pattern are now solved much more efficiently with the patterns brought by the Stream API. But Java 8 is not only about lambdas, streams and collectors, there is also a new Java Date and Time API which are covered in this course. This API fixes all the flaws of the previous Date/Calendar API and brings new, very useful, concepts and tools. Many new features that bring a functional programming approach have been added to the Collection API. This is also covered in detail. Many more things are covered; little things, scattered here and there in the JDK, like this new StringJoiner class, useful to join strings with a prefix, a postfix, and a separator. JavaFX and Nashorn are also quickly covered, to show the FXML way to describe Graphical User Interfaces, and the new ways to describe JavaFX in Javascript using Nashorn.

 

Download

Link GoogleDrivehttps://drive.google.com/folderview?id=0B5U6Rykwg1bVd3BvMFZoWGViZnM&usp=sharing

Nội dung chi tiết

Introduction to Lambda Expressions in Java 8

  • Introduction, Targeted Audience
  • Module Outline
  • The FileFilter Example
  • A First Lambda Expression
  • Live Coding: A First Lambda Expression
  • Live Coding: Runnable and Comparator Examples
  • Several Ways of Writing Lambda Expressions
  • Three Questions About Lambda Expressions
  • Functional Interfaces
  • Is a Lambda Expression an Object?
  • The Functional Interfaces Toolbox
  • Method References
  • Processing Collections With Lambdas
  • Changing the Way Interfaces Work?
  • Default and Static Methods in Java 8 Interfaces
  • New Patterns: The Predicate Interface Example
  • Live Coding: New Patterns Examples
  • Module Wrap Up

Java 8 Stream API and Collectors

  • Introduction, Module Outline
  • The Map / Filter / Reduce Algorithm
  • What Is a Stream?
  • Definition of a Stream in Java 8
  • Building and Consuming a Stream
  • Filtering a Stream
  • Live Coding: Consuming and Filtering a Stream
  • Lazy Operations on a Stream
  • Lice Coding: Intermediary and Terminal Operations
  • Wrapping up Intermediary and Terminal Operations
  • The Map Operation
  • The Flatmap Operation
  • Lice Coding: Map and Flatmap Examples
  • Wrapping Up Map and Filter on a Stream
  • Reduction, Functions, and Bifunctions
  • Reduction of the Empty Set: Identity Element
  • Optionals
  • Pattern for the Optionals
  • Wrapping Up Reduction Operations
  • Terminal Operations
  • Live Coding: Reductions, Optionals
  • Wrapping Up Operations and Optionals
  • Collectors, Collecting in a String, in a List
  • Collecting in a Map
  • Live Coding: Processing Streams
  • Wrapping Module

Java 8 Date and Time API

  • Introduction and Outline
  • The Old java.util.Date API
  • Why Does Immutability Matter?
  • The Instant Class and the Duration Class
  • The LocalDate Class and the Period Class
  • Live Coding: Local Dates and Periods Examples and Corner Cases
  • Computing Dates From Other Dates
  • The LocalTime Class
  • Dealing With Time Zones: The ZonedTime Class
  • Printing Dates and Times: The DateTimeFormatter
  • From Legacy Code to the New Date and Time API
  • Conclusion and Wrap-Up

Strings, IO, and Other Bits and Pieces

  • Introduction and Outline
  • Strings and StringJoiner
  • Java I/O: Reading Text Files
  • Java I/O: Exploring Directories
  • New Methods on Iterable, Collection, and List
  • Comparator: Patterns and Utilities
  • Numbers, Method References, and Hashcodes
  • Map: Enhancements of Existing Methods
  • Map: The Compute and Merge Methods
  • Live Coding: General Map Enhancements
  • Live Coding: Map Merging
  • Live Coding: Building Bimaps
  • Annotations
  • Conclusion and Wrap Up

Introduction to Java FX 8

  • Introduction and Outline
  • First Key Concepts on a Simple Example
  • Live Coding a Hello World Example
  • Setting Up an Interface Using the JavaFX API
  • Setting Up an Interface Using the FXML File
  • Controller and Dependency Injection
  • Live Coding: Setting Up a UI With FXML and Java Controllers
  • Conclusion and Wrap Up

Nashorn: A JavaScript Engine on the JVM

  • Introduction and Outline
  • jjs: The Nashorn REPL
  • Livecoding: The REPL in Action
  • Running Javascript in Java Classes
  • Writing and Launching JavaFX UI in Javascript
  • Live Coding: JavaFX With Nashorn
  • Conclusion and Wrap Up

Email: edwardthienhoang@gmail.com

http://www.edwardthienhoang.wordpress.com

Java 8 Tutorial: Lambda expression and Streams in Java 8

java8lambda

Giới thiệu

Hôm nay mình sẽ share một bộ video học Java 8 từ LiveLessions. Với hơn 3 giờ học, các bạn sẽ nắm được những đặc điểm nổi bật nhất trong Java 8 là Lambda Expression và Stream.

Tóm tắt nội dung

  • Cách sử dụng những đặc điểm quan trọng nhất trong Java 8: Lambda Expressions và Streams.
  • Những kỹ thuật sử dụng lambda expression: method references, lambda building blocks in the java.util.function package, effectively-final local variables, the @FunctionalInterface annotation, and higher-order functions.
  • Các method mới liên quan đến Stream: forEach, map, filter, reduce, etc.
  • Infinite (unbounded) streams
  • Parallel streams.
  • Lazy evaluation and short-circuit stream operations.
  • Những đặc điểm khác trong Java 8: Functional Interface và Optional class.

Video

Bộ video này được upload trên Youtube bởi bạn Tiep Phan, mình xin mạn phép chia sẻ lại.

Nội dung chi tiết

Introduction

  • Introduction to Java 8: Lambda Expressions and Streams LiveLessons

Lesson 1: Java 8: Installation, Setup, and Review of Supporting Topics

  • Learning objectives
  • 1.1 Getting Started with Java 8
  • 1.2 Java 8 References
  • 1.3 Quick Review of Pre-Lambda Handlers
  • 1.4 Quick Review of Building Generic Methods and Classes
  • 1.5 Wrap-Up

Lesson 2: Lambda Expressions Part 1 – Basics

  • Learning objectives
  • 2.1 Motivation and Overview
  • 2.2 Lambdas: Most Basic Form
  • 2.3 Type Inferencing
  • 2.4 Expression for Body: Implied Return Values
  • 2.5 Comparing Java and JavaScript Sorting
  • 2.6 Omitting Parens for One-Arg Lambdas
  • 2.7 Using Effectively Final Local Variables
  • 2.8 The @FunctionalInterface Annotation
  • 2.9 Method References
  • 2.10 The java.util.function Package
  • 2.11 Final Example
  • 2.12 Wrap-Up

Lesson 3: Lambda Expressions Part 2 – Lambda Building Blocks in java.util.function

  • Learning objectives
  • 3.1 Lambda Building Blocks in java.util.function: Overview
  • 3.2 Predicate
  • 3.3 Function and BiFunction
  • 3.4 Consumer
  • 3.5 Supplier
  • 3.6 BinaryOperator
  • 3.7 Wrap-Up

Lesson 4: Lambda Expressions Part 3

  • Learning objectives
  • 4.1 Variable Scoping
  • 4.2 Method References: Details
  • 4.3 Java 8 Interfaces: Default Methods and Static Methods
  • 4.4 Methods that Return Lambdas
  • 4.5 Wrap-Up

Lesson 5: Streams Part 1

  • Learning objectives
  • 5.1 Overview of Streams
  • 5.2 Getting Standard Data Structures Into and Out of Streams
  • 5.3 Core Stream Methods: Overview
  • 5.4 forEach – Calling a Lambda on Each Element of a Stream
  • 5.5 map – Transforming a Stream by Passing Each Element through a Function
  • 5.6 filter – Keeping Only the Elements that Pass a Predicate
  • 5.7 findFirst – Returning the First Element of a Stream while Short-Circuiting Earlier Operations
  • 5.8 Lazy Evaluation
  • 5.9 Wrap-Up

Lesson 6: Streams Part 2

  • Learning objectives
  • 6.1 reduce: Combining Stream Elements
  • 6.2 collect: Fancier Stream Output
  • 6.3 Operations that Limit the Stream Size: limit, substream
  • 6.4 Operations that Use Comparisons: sorted, min, max, distinct
  • 6.5 Operations that Check Matches: allMatch, anyMatch, noneMatch, count
  • 6.6 Parallel Streams
  • 6.7 Infinite (Unbounded On-the-Fly) Streams
  • 6.8 Wrap-Up

Summary

  • Summary of Java 8: Lambda Expressions and Streams LiveLessons

 

Email: edwardthienhoang@gmail.com

http://www.edwardthienhoang.wordpress.com

Eclipse tutorial: Hướng dẫn cài đặt và sử dụng CheckStyle plugin

Eclipse tutorial: Hướng dẫn cài đặt và sử dụng CheckStyle plugin

Bài viết này sẽ hướng dẫn các bạn cài đặt và sử dụng CheckStyle plugin trong Eclipse. CheckStyle là một trong những plugin phổ biến nhất trong Eclipse, giúp chúng ta kiểm tra coding convention (quy ước viết mã) dựa trên những quy tắc đã được định nghĩa trước đó. Các bạn có thể tham khảo thêm bộ quy tắc đồ sộ của CheckStyle tại đây: http://checkstyle.sourceforge.net/availablechecks.html

Cài đặt

Chọn Menu Help –> Install New Software… và nhập vào địa chỉ sau:
http://eclipse-cs.sf.net/update/

1. Download

Sau đó tiến hành cài đặt với vài cú click, sau đó khởi động lại Eclipse

Để kiểm tra việc cài đặt có thành công hay không, các bạn vào Menu Window –> Preferences sẽ thấy mục CheckStyle

2. InstallSuccess

Định nghĩa những quy ước

Mặc định CheckStyle dùng bộ quy ước đã được định nghĩa sẵn từ Sun, tuy nhiên bạn cũng có thể tạo ra những quy ước riêng cho mình, tùy theo đặc thù của dự án.
Đầu tiên chúng ta sẽ tạo 1 configuration file có tên là CheckStyleTemplate.xml với nội dung như sau:

<?xml version="1.0" encoding="UTF-8"?>
<!--
Checkstyle configuration (v5.x)
-->
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
    <property name="severity" value="warning"/>
</module>

Root tag của file là module, bên trong hiện chỉ có 1 child tag là

<property name="severity" value="warning"/>

với ý nghĩa sẽ hiện những thông báo dưới dạng warning trong Eclipse khi phát hiện những đoạn code vi phạm quy tắc.

Tiếp theo là thêm những quy tắc vào trong file config này, các bạn có thể tham khảo danh sách các quy tắc mà CheckStyle hỗ trợ tại: http://checkstyle.sourceforge.net/availablechecks.html

Trong ví dụ này, mình sẽ sử dụng 3 quy tắc: StrictDuplicateCode (không cho phép có những đoạn code trùng lặp), EqualsHashCode (khi override phương thức equals thì bắt buộc phải override phương thức hashCode) và MethodLength (giới hạn số dòng tối đa trong 1 method)

<?xml version="1.0" encoding="UTF-8"?>
<!--
Checkstyle configuration (v5.x)
-->
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
<module name="Checker">
    <property name="severity" value="warning"/>
	<module name="StrictDuplicateCode">
		<property name="min" value="15"/>
	</module>
	<module name="TreeWalker">
		<module name="EqualsHashCode"/>
		<module name="MethodLength">
		<property name="tokens" value="METHOD_DEF, CTOR_DEF"/>
		<property name="max" value="30"/>
		<property name="countEmpty" value="false"/>
	</module>
	</module>
</module>

Áp dụng những quy tắc vào dự án

Import những quy tắc trên vào Eclipse bằng cách chọn New trong cửa sổ CheckStyle, sau đó chọn External Configuration Filebrowse đến file config CheckStyleTemplate.xml

3. CreateNew

Sau đó chọn Set as Default để áp dụng bộ quy tắc này cho các project trong Eclipse workspace hiện tại

4. SetDefault

Kiểm tra source code với CheckStyle

Với file config như trên, ta sẽ áp dụng kiểm tra cho đoạn code dưới đây

public class TestCheckStyle {

	public static void main(String[] args) {
		foo();
	}

	private static void foo() {
		System.out.println("Bla bla bla...");
		int a = 10;
		int b = 20;
		int c = 30;
		int d = 40;
		int e = a + b + c + d;
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
	}

	@Override
	public boolean equals(Object o) {
		if(o instanceof TestCheckStyle) {
			return true;
		}
		return false;
	}
}

Click chuột phải vào file Java, package hoặc Project cần kiểm tra và chọn CheckStyle –> Check code with CheckStyle

5. Check

Nếu đoạn code nào vi phạm các quy tắc trên sẽ được hightlight như hình bên dưới:

6. FoundError

CheckStyle chỉ hỗ trợ phát hiện ra những đoạn code vi phạm quy tắc chứ không hỗ trợ gợi ý sửa chúng ra sao. Vì vậy việc còn lại của các bạn là sửa những vi phạm đó để tránh những lỗi về coding convention.

Kết thúc bài giới thiệu về CheckStyle plugin ở đây. Hi vọng có thể giúp ích cho các bạn trong việc kiểm tra và tránh những lỗi về coding convention trong dự án

Nguồn: https://edwardthienhoang.wordpress.com
Email: edwardthienhoang@gmail.com

Hướng dẫn sử dụng plugin Vanaraha để kiểm tra code trùng lặp

Hướng dẫn sử dụng plugin Vanaraha để kiểm tra code trùng lặp

Trong bài viết này mình sẽ giới thiệu về plugin Vanaraha, một công cụ để kiểm tra những đoạn code trùng lặp có trong chương trình, từ đó chúng ta có thể đặt những đoạn code giống nhau đó trong 1 phương thức và tái sử dụng lại.

Download

Việc sử dụng Vanaraha rất đơn giản, các bạn vào trang chủ tại: https://code.google.com/p/vanaraha/ sau đó download gói jar ở mục Download về và bỏ vào trong thư mục eclipse\plugins. Quá trình cài đặt đã hoàn tất, khởi động lại Eclipse nếu các bạn đã mở trước đó.

Tạo 1 class để test

public class TestDuplicateCode {

	public static void main(String[] args) {

	}

	private static void foo1() {
		int a = 10;
		int b = 20;
		int c = 30;
		int d = 40;
		int e = a + b + c + d;
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
	}

	private static void foo2() {
		System.out.println("Bla bla bla...");
		int a = 10;
		int b = 20;
		int c = 30;
		int d = 40;
		int e = a + b + c + d;
		System.out.println(a);
		System.out.println(b);
		System.out.println(c);
		System.out.println(d);
		System.out.println(e);
		System.out.println("Bla bla bla... again");
	}
}

Click chuột phải vào class TestDuplicateCode hoặc 1 package hoặc nguyên cả Project, sau đó chọn Vanahara (Find Duplicates) –> Find duplicated in this file(s) để tìm ra những đoạn code trùng lặp.

1. HuongDan

Ngoài ra Vanaraha cũng có 1 số setting tùy chỉnh như:
File Extension: để filter ra những loại file cần kiểm tra

2. File Extension
Minimum number of duplicate line(threshold): chỉ tính những đoạn code trùng lặp từ n dòng trở lên.
Và một số tùy chỉnh khác

3. Threshold

Kết thúc phần giới thiệu về plugin Vanahara tại đây, hi vọng bài viết sẽ giúp ích cho các bạn trong quá trình refactor để loại bỏ những đoạn code trùng lặp không cần thiết.

Nguồn: https://edwardthienhoang.wordpress.com

Email: edwardthienhoang@gmail.com

Hướng dẫn sử dụng VisualVM để đo hiệu năng chương trình Java

Hướng dẫn sử dụng VisualVM để đo hiệu năng chương trình Java

Hiệu năng chương trình bao gồm tốc độ xử lý, lượng RAM tiêu tốn và cả dung lượng ổ cứng tiêu tốn. Trong thời buổi mà ổ cứng lên tới cả Terabyte thì thì việc tiêu tốn vài GB để lưu trữ data cũng không được bận tâm nhiều lắm. Còn tốc độ xử lý và độ ngốn RAM thì luôn là bài toán với tất cả lập trình viên từ xưa đến nay.

Về thời gian thực thi, có một sốc cách để tính được thời gian thực thi của mỗi hàm, hay một vài đoạn code bằng cách gọi System.currentTimeMillis() ở đầu đoạn code và cuối đoạn code, qua đó tính được thời gian thực thi, hoặc cũng có thể dùng logging tool. Tuy nhiên những cách làm trên rất thủ công và tốn thời gian.

Còn về memory tiêu tốn, có thể mở Task Manager của Window lên để xem process của mình chạy hết bao nhiêu RAM hoặc dùng 1 số lớp có sẵn trong Java để trace ra heap dump tại từng thời điểm. Cũng giống như ở trên, việc làm này gây tốn thời gian và không chính xác nếu ta muốn xem trong chương trình hiện tại có bao nhiêu đối tượng A, B, C đang được khởi tạo, và tổng bộ nhớ dùng cho chúng là bao nhiêu thì không làm được.

Thay vì dùng những cách thủ công để đo hiệu năng của chương trình, chúng ta có thể nghĩ đến các công cụ giúp chúng ta làm chuyện đó. Chỉ cần lên mạng search vài từ khóa như: Java performance reasurement tool, Java performance analysis tool… sẽ cho các bạn rất nhiều lựa chọn.

Trong bài viết này, mình giới thiệu về VisualVM. Một công cụ hỗ trợ rất nhiều tính năng giúp cho việc đo lường hiệu năng của chương trình một cách dễ dàng và đặc biệt là nó cũng cung cấp cho các bạn một cái nhìn trực quan ví dụ như về các thread đang chạy hay thời gian thực thi của những hàm hiện tại… OK let’s start!

Đầu tiên các bạn tải VisualVM bản mới nhất tại đây:
http://visualvm.java.net/download.html

Lưu ý là VisualVM chỉ chạy được trên JDK 6u7 trở lên, nếu máy các bạn chưa cài JDK 6 thì có thể download bản mới nhất tại đây:
http://www.oracle.com/technetwork/java/javase/downloads/index.html?ssSourceSiteId=otnjp

Overview

Sau đó bung nén ra và mở file visualvm_137\bin\visualvm.exe lên sẽ có giao diện như thế này

1. StartScreen

Không chần chừ nữa, hãy tạo 1 project Java sau đó Run và xem ta có thể làm gì với VisualVM

public class OverviewTest {

	public static void main(String[] args) {
		
		System.out.println("Hello VisualVM");
		
		// Hey! I'm waiting you to switch to VisualVM
		// and see I'm also in there
		// just in 1 minute
		try {
			Thread.sleep(60000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

Sau khi run đoạn code trên, các bạn chuyển qua VisualVM sẽ thấy được 1 process Java tương ứng với đoạn chương trình trên, double click vào sẽ thấy được thông tin overview về chương trình như: Process ID, main class, argument, phiên bản Java đang dùng…

2. OverviewAnProcess

Bây giờ hãy dùng VisualVM để kiểm tra các vấn đề về performance như:

  • Thời gian thực thi qua đó cải thiện tốc độ chương trình
  • Độ tiêu thụ memory cùng với việc kiểm tra và giải quyết memory leak
  • Theo dõi tất cả các thread đang chạy trong chương trình cùng với việc kiểm tra và giải quyết deadlock

Đo thời gian thực thi

public class PerformanceTest {

	public static void main(String[] args) {

		// Hey! I'm waiting you to switch to VisualVM
		// and see I'm also in there
		// just in 20 seconds
		try {
			Thread.sleep(20000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < 10; i++) {
			PerformanceClass testClass = new PerformanceClass();
			testClass.foo1();
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}
public class PerformanceClass {
	
	private int mField = 10;
	
	public void foo1() {
		mField += 3;
		System.out.println("foo1()");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		foo2();
		foo3();
	}
	
	public void foo2() {
		mField += 2;
		System.out.println("foo2()");
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		foo3();
	}
	
	public void foo3() {
		mField += 1;
		System.out.println("foo3()");
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Sau khi run chương trình, các bạn chuyển qua VisualVM, tìm process của chương trình đang chạy và double click vào, chọn thẻ Sampler và chọn button CPU, nó sẽ ra như sau:

3. CPU

Các bạn có thể nhìn thấy sự trực quan trên màn hình. Và có thể thấy thời gian thực thi của các hàm đang được gọi. Sau khi chương trình kết thúc ta có được kết quả cuối cùng

4.

Dựa vào kết quả trên, có thể nhận biết được thời gian thực thi của mỗi hàm qua cột “Self Time“. Từ đó các bạn có thể kết luận rằng hàm nào đang tốn nhiều thời gian xử lý hơn bạn mong muốn, từ đó để đưa ra những điều chỉnh thích hợp để tăng tốc độ thực thi. Nếu muốn biết thời gian chiếm CPU thì có thể xem thêm ở cột “Self Time (CPU)“.

Đo độ tiêu thụ memory

Cùng đoạn code như trên, khi các bạn chạy chương trình Java và chuyển sang VisualVM, chọn thẻ Sampler và chọn button Memory, nó sẽ ra như sau:

5. MemoryOverview

Trong màn hình này, tại thẻ Heap Histogram, các bạn có thể xem trực quan số lượng class đã được load lên, tổng số instance của một lớp đang tồn tại trong bộ nhớ Heap và tổng số byte của chúng.

Chuyển qua thẻ Per thread allocations sẽ cho các bạn thấy các thông số giống ở trên nhưng cho từng thread.

Bên cạnh đó, chức năng Snapshot cho phép các bạn lưu / chụp lại các thông tin ngay tại thời điểm đó.

Bên cạnh chức năng theo dõi memory trực quan này, VisualVM còn hỗ trợ chúng ta xem HeapDump của chương trình đang chạy ngay thời điểm hiện tại. HeapDump sẽ cung cấp cho chúng ta nhiều thông tin hơn về giá trị của các biến thành viên trong instance đó. Để load HeadDump của chương trình hiện tại, các bạn click phải vào process của chương trình, sau đó chọn HeapDump, 1 tab HeapDump mới sẽ mở ra, các bạn chọn qua nút Classes. Tại đây các bạn có thể double click vào 1 class nào đó sẽ hiển ra danh sách các instance của lớp đó, double click vào 1 đối tượng, bạn sẽ thấy thông tin về các field của nó và danh sách các đối tượng khác đang reference đến nó.

7. DetailInstance

Chẩn đoán memory leak

Bây giờ hãy chuyển sang 1 ví dụ để hiểu VisualVM cung cấp thông tin cho chúng ta như thế nào khi 1 chương trình bị leak memory

Các bạn có thể lên mạng để tìm hiểu 1 số nguyên nhân dẫn đến việc leak memory trong Java, ở đây mình lấy 1 ví dụ về hàm subString. Từ Java 6 trở về trước, khi gọi hàm subString trên 1 đối tượng String luôn luôn gây ra memory leak, và lỗi này đã được fix từ Java 7.

import java.util.ArrayList;
import java.util.List;

class Stringer {
	static final int MB = 1024 * 1024;

	static String createLongString(int length) {
		StringBuilder sb = new StringBuilder(length);
		for (int i = 0; i < length; i++)
			sb.append('a');
		sb.append(System.nanoTime());
		return sb.toString();
	}

	public static void main(String[] args) {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		List<String> substrings = new ArrayList<String>();
		for (int i = 0; i < 100; i++) {
			String longStr = createLongString(MB);
			// Leak here. Just in Java 6-
			String subStr = longStr.substring(1, 10);
			substrings.add(subStr);
		}
		
		try {
			Thread.sleep(20000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

Để tái hiện memory leak, mình sẽ chạy chương trình trên Java 6, kết quả đoạn code trên sẽ như sau

8. SubStringJava6

Còn khi chạy trên Java 8, thì kết quả như sau.

9. SubStringJava8

Qua 2 ví dụ trên, cho ta thấy nếu memory tiêu tốn trong chương trình tăng một cách bất thường hoặc biến thiên tăng dần theo thời gian, thì có thể chương trình bạn đang gặp vấn đề memory leak.

Theo dõi tất cả các thread đang chạy

VisualVM cũng hỗ trợ việc theo dõi một cách trực quan về vòng đời của tất cả các thread đang chạy trong chương trình. Với mỗi trạng thái của Thread sẽ được biểu diễn bằng một màu khác nhau, bạn sẽ dễ dàng hình dung ra mọi thứ đang hoạt động thế nào. Bắt đầu với 1 đoạn code test

public class ThreadTest {

	public static void main(String[] args) {
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}

		for (int i = 0; i < 100; i++) {
			new Thread(new Runnable() {
				@Override
				public void run() {
					for (int i = 0; i < 100; i++) {
						System.out
								.println(i + Thread.currentThread().getName());
						try {
							URL url = new URL(
									"http://www.google.com/");
							URLConnection conn = url.openConnection();
							conn.connect();
							System.out.println("Dude its Working Fine ! ");
						} catch (Exception e) {
							System.out.println("Not Working");
						}
					}

				}
			}).start();
		}
	}

}

Chuyển sang VisualVM, double click vào ProcessID, sau đó chọn thẻ Thread Dump sẽ thấy được các thread đang chạy trong chương trình

10. ThreadVisual

Ứng với mỗi trạng thái của thread được biểu diễn bằng các màu khác nhau.

  • Màu xanh lá: Thread đang chạy
  • Màu tím: Thread đang sleep khi gọi câu lệnh Thread.sleep(…)
  • Màu vàng: Thread đang wait khi gọi hàm wait()
  • Màu đỏ: Thread đang bị block và đợi đến lượt để vào khối lệnh synchronize

Kiểm tra deadlock trong chương trình

Giả sử như có rất nhiều thread đang bị block để đợi đến lượt vào khối lệnh synchronize mà thread hiện tại đang giữ. Tuy nhiên vì một lý do nào đó mà thread hiện tại không thể thoát ra khối lệnh synchronize để nhường chỗ cho thread khác dẫn đến các thread khác sẽ phải chờ rất lâu thậm chí là mãi mãi dẫn đến việc “tắc đường” làm ngưng trệ toàn bộ chương trình. Vì vậy trong môi trường multithread, khi thấy chương trình mình bị “đơ” thì rất có thể đã xảy ra deadlock. Và để chắc chắn hơn, các bạn có thể dùng VisualVM để kiểm tra có deadlock hay không. Ví dụ như đoạn code dưới đây, cùng kiểm tra xem hình hài của deadlock như thế nào. :D

public class DeadlockTest {

	public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
     
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
         
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();
         
    }

}
class SyncThread implements Runnable{
    private Object obj1;
    private Object obj2;
 
    public SyncThread(Object o1, Object o2){
        this.obj1=o1;
        this.obj2=o2;
    }
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " acquiring lock on "+obj1);
        synchronized (obj1) {
         System.out.println(name + " acquired lock on "+obj1);
         work();
         System.out.println(name + " acquiring lock on "+obj2);
         synchronized (obj2) {
            System.out.println(name + " acquired lock on "+obj2);
            work();
        }
         System.out.println(name + " released lock on "+obj2);
        }
        System.out.println(name + " released lock on "+obj1);
        System.out.println(name + " finished execution.");
    }
    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Khi chạy VisualVM sẽ thấy như sau

11. Deadlock

3 thread t1, t2, t3 hiện đang ở trạng thái màu đỏ, nghĩa là cả 3 cùng đang chờ lẫn nhau dẫn đến không thread nào có thể chạy tiếp được dẫn đến deadlock.

Kết thúc bài viết hi vọng đã chia sẻ cho các bạn một công cụ hữu ích trong việc theo dõi và đo hiệu năng chương trình Java.

Nguồn: https://edwardthienhoang.wordpress.com

Email: edwardthienhoang@gmail.com

Java 8 Tutorial: Giới thiệu Nashorn Engine

Java 8 Tutorial: Giới thiệu Nashorn Engine

1.Giới thiệu

Sự ra đời của Java 8 trong năm 2014 này có rất nhiều thay đổi mới trong đó chúng ta phải kể đến việc phát triển Nashorn Engine nhằm thay thế cho Rhino Engine cũ và tích hợp chúng vào trong JVM để làm cho lập trình Java và javascript trở nên dễ dàng hơn và có hiệu năng cao hơn. trong bài này tôi giới thiệu với các bạn về Nashorn và cách sử dụng chúng trong Java 8.

2. Nashorn là gì?

Nashorn là một engine thực thi javascript mới, tương tự như các engine V8 của trình duyệt Chrome hay SquirrelFish engine của WebKit. Từ năm 1997, Java đã có thể làm việc (hạn chế) với javascript thông qua engine Rhino; trong Java 7, việc thực thi javascript trên JVM thông qua cơ chế invokeDynamic. Với Java 8, bằng việc tích hợp hoàn toàn Nashorn vào JVM, lập trình viên có thể sử dụng javascript khai thác các thư viện có sẵn của java và ngược lại. Theo thử nghiệm thì Nashorn chạy nhanh gấp 5 lần Rhino và đòi hỏi ít bộ nhớ hơn.

3. Tại sao Nashorn lại được phát triển?

Nó được phát triển để thay thế cho javascript engine đã quá cũ trong jvm từ năm 1997
Tạo ra cầu nối giữa java và javascript. ( cây cầu này được tạo ra trong môi trường JVM)
Giải quyết vấn đề không tương thích giữa java và javascript.
Nâng cao performance của việc thực thi javascript trong java. thay thế cho Rhino engine đã quá lỗi thời.
Bằng việc tích hợp javascript trong java code. bạn có thể chỉnh sửa, mở rộng, sử dụng các ưu điểm của các api có sẵn trong java. (nghĩa là bạn có thể truy cập và sử dụng các thư viện có sẵn trong java để thực thi từ javascript)

4. Script engine & script language là gì?

Scripting engine: là một trình thông dịch của các ngôn ngữ scripting. được viết sẵn trong java JDK nằm trong javax.script package.
Script language: là ngôn ngữ lập trình có hỗ trợ có khả năng viết các script (php,ruby, python , javascript..). đối với các ngôn ngữ cần biên dịch như java, .net thì cần phải có trình biên dịch dịch ra mã bytecodes trước khi chúng được chạy. còn đối với script language thì chúng chỉ được dịch tại thời điểm chạy. bởi một script engine.
Hầu hết các script language đều là có khai báo các kiểu dữ liệu động. (nghĩa là có thể khai báo các kiểu dữ liệu khác nhau cho cùng một biến., và khi bạn tạo một biến cũng không cần phải khai báo kiểu dữ liệu. chỉ khi nào bạn chạy nó thì mới cần khai báo.).
Tài liệu “Java Specification Request (JSR) 223″ có mô tả rõ những vấn đề gặp phải khi tích hợp java và javascript trong java. http://jcp.org/en/jsr/detail?id=223

5. Javascripting API:

Nó là sự cài đặt JSR 223 trong ứng dụng java. Nhằm để nhúng javascript vào trong java.

6. Nashorn engine:

Là một javascript engine viết dựa trên tài liệu mô tả của ECMAScript (javascript) engine được tích hợp trong JDK. nó đã được phát triển đầy đủ bởi oracle và được tích hợp trong jdk8. tương thích hoàn toàn với javascript.

7. Làm thế nào để sử dụng Nashorn?

Cần import thư viện javax.script.*; để sử dụng script engine trong java.
khởi tạo một đối tượng Nashorn Script Engine sử dụng ScriptEngineManager của java.
sử dụng script engine vừa tạo để thực hiện một đoạn mã javascript.

VD :

 import javax.script.*;
 public class EvalScript { 
 public static void main(String[] args) throws Exception { 
 ScriptEngineManager manager = new ScriptEngineManager(); 
 ScriptEngine engine = manager.getEngineByName("nashorn");
    // evaluate JavaScript code
   engine.eval("print('Hello, World')");
 }}

 

8. Các cách sử dụng các thư viện có sẵn của Java bằng script engine

sử dụng các class của Java.

import javax.script.*;
public class EvalFile {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");

    // evaluate JavaScript code
    engine.eval(new java.io.FileReader("script.js"));
}}

Đưa một object của Java thành một biến global của script engine:

import javax.script.*; 
import java.io.*;
public class ScriptVars { public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager(); 
ScriptEngine engine =  manager.getEngineByName("nashorn");

    // create File object
    File f = new File("test.txt");
    // expose File object as a global variable to the engine
    engine.put("file", f);
    // evaluate JavaScript code and access the variable
    engine.eval("print(file.getAbsolutePath())");
}}

Thực thi một Script function từ script engine.

  import javax.script.*;
  public class InvokeScriptFunction { 
  public static void main(String[] args) throws Exception { 
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("nashorn");

    // evaluate JavaScript code that defines a function with one parameter
    engine.eval("function hello(name) { print('Hello, ' + name) }");

    // create an Invocable object by casting the script engine object
    Invocable inv = (Invocable) engine;

    // invoke the function named "hello" with "Scripting!" as the argument
    inv.invokeFunction("hello", "Scripting!");
}
}

Thực thi một script method của Object

 import javax.script.*;
 public class InvokeScriptMethod { 
 public static void main(String[] args) throws Exception {
 ScriptEngineManager manager = new ScriptEngineManager();
 ScriptEngine engine = manager.getEngineByName("nashorn");

    // evaluate JavaScript code that defines an object with one method
    engine.eval("var obj = new Object()");
    engine.eval("obj.hello = function(name) { print('Hello, ' + name) }");

    // expose object defined in the script to the Java application
    Object obj = engine.get("obj");

    // create an Invocable object by casting the script engine object
    Invocable inv = (Invocable) engine;

    // invoke the method named "hello" on the object defined in the script
    // with "Script Method!" as the argument
    inv.invokeMethod(obj, "hello", "Script Method!");
   }}

chú ý: không phải tất các các script engine đều được cài đặt Invocable interface. trong ví dụ trên thì chúng ta sử dụng nashorn engine đã được cài đặt invocabkle interface.

Cài đặt một Java interface bằng script functions:

   public class ImplementRunnable {
   public static void main(String[] args) throws Exception {
   ScriptEngineManager manager = new ScriptEngineManager();
   ScriptEngine engine = manager.getEngineByName("nashorn");

    // evaluate JavaScript code that defines a function with one parameter
    engine.eval("function run() { print('run() function called') }");

    // create an Invocable object by casting the script engine object
    Invocable inv = (Invocable) engine;

    // get Runnable interface object
    Runnable r = inv.getInterface(Runnable.class);

    // start a new thread that runs the script
    Thread th = new Thread(r);
    th.start();
    th.join();
} }

Cài đặt một Java interface bằng script object methods.

  import javax.script.*;
  public class ImplementRunnableObject {
  public static void main(String[] args) throws Exception {
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("nashorn");

    // evaluate JavaScript code that defines a function with one parameter
    engine.eval("var obj = new Object()")
    engine.eval("obj.run = function() { print('obj.run() method called') }");

    // expose object defined in the script to the Java application
    Object obj = engine.get("obj");

    // create an Invocable object by casting the script engine object
    Invocable inv = (Invocable) engine;

    // get Runnable interface object
    Runnable r = inv.getInterface(obj, Runnable.class);

    // start a new thread that runs the script
    Thread th = new Thread(r);
    th.start();
    th.join();
 } }

Sử dụng biến trong các phạm vi khác nhau.

  public class MultipleScopes { 
  public static void main(String[] args) throws Exception {
  ScriptEngineManager manager = new ScriptEngineManager(); 
  ScriptEngine engine = manager.getEngineByName("nashorn");

    // set global variable
    engine.put("x","hello");

    // evaluate JavaScript code that prints the variable (x = "hello")
    engine.eval("print(x)");

    // define a different script context
    ScriptContext newContext = new SimpleScriptContext();
    newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
    Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);

    // set the variable to a different value in another scope
    engineScope.put("x", "world");

    // evaluate the same code but in a different script context (x = "world")
    engine.eval("print(x)", newContext);
} }

 

9. sử dụng truy cập đến các thư viện có sẵn của Java trong script engine

primitive data type:

   var ArrayList = Java.type("java.util.ArrayList"); 
   var intType = Java.type("int");
   var StringArrayType = Java.type("java.lang.String[]"); 
   var int2DArrayType = Java.type("int[][]");

* Object data type:

      var ArrayList = Java.type("java.util.ArrayList");
      var defaultSizeArrayList = new ArrayList;
      var customSizeArrayList = new ArrayList(16);

Truy cập inner class bằng $ sign:

var Float = Java.type("java.awt.geom.Arc2D$Float");

sử dụng import class or package:

   // Load compatibility script 
   load("nashorn:mozilla_compat.js");
   // Import the java.awt package 
   importPackage(java.awt); 
 // Import the java.awt.Frame class
  importClass(java.awt.Frame); 
  // Create a new Frame object 
  var frame = new java.awt.Frame("hello"); 
  // Call the setVisible() method 
  frame.setVisible(true);
  // Access a JavaBean property 
  print(frame.title);

Nashorn thực sự là một cầu nối giữa Java và javascript. Nó thực sự đã làm cho việc thực thi nhiều ngôn ngữ trong Java trở nên dễ dàng hơn, nâng cao hiệu năng xử lý javascript trong Java

Nguồn:

http://tech.blog.framgia.com/vn/?p=2857

http://txnam.net/nhung-diem-moi-trong-java-8.html

Checked và Unchecked Exception trong Java

Checked và Unchecked Exception trong Java

Cơ bản

Trong Java có 2 loại exception: checked và unchecked. Tất cả các checked exception được kế thừa từ lớp Exception ngoại trừ lớp RuntimeException. RuntimeException là lớp cơ sở của tất cả các lớp unchecked exception. Đó cũng là dấu hiệu để nhận biết đâu là checked exception và đâu là unchecked exception. Cùng xem qua hierarchy của tất cả các lớp exception:

ExceptionHierarchy

Khác nhau giữa Checked và Unchecked Exception

Điểm khác biệt giữa các lớp checked và unchecked expcetion chính là thời điểm xác định được expcetion có thể xảy ra. Đối với checked exception, việc kiểm tra được thực hiện ngay thời điểm compile time, một số IDE sẽ giúp chúng ta bằng cách hiển thị lỗi cú pháp nếu ta gọi một method throw ra bất kỳ checked exception nào mà không được catch. Một số checked exception tiêu biểu như: IOException, InterruptedException, XMLParseException.. Còn đối với unchecked exception, việc xác định có exception xảy ra hay không chỉ có thể thực hiện ở thời điểm runtime, và các IDE sẽ không giúp chúng ta xác định được chuyện đó. Một số unchecked exception tiêu biểu là: NullPointerException, IndexOutOfBoundsException, ClassCastException… Hãy xem các ví dụ để hiểu rõ hơn.

Checked exception

Hãy xét qua ví dụ với IOException:

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class MainCheckedAndUncheckedException {

	public static void main(String[] args) {

		BufferedReader br = null;

		try {

			String sCurrentLine;

			br = new BufferedReader(new FileReader("C:\\testing.txt"));

			while ((sCurrentLine = br.readLine()) != null) {
				System.out.println(sCurrentLine);
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null)
					br.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}

	}
}

Ở đoạn trên, nếu ta remove phần try-catch thì IDE sẽ báo lỗi:

Unhandled exception type FileNotFoundException đối với method: FileReader(…)
Unhandled exception type IOException đối với method: readLine()

Bây giờ hãy viết riêng một method để test

public class MainCheckedAndUncheckedException {

	public static void main(String[] args) {
		try {
			doParseXML();
		} catch (XMLParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void doParseXML() throws XMLParseException, IOException {
		doOpenXML();
		// Do parse XML. This method may be thrown a checked exception
	}

	private static void doOpenXML() throws IOException {
		// Do open XML. This method may be thrown a checked exception
	}
}

Method doOpenXML được dánh dấu là sẽ throw ra IOException, do vậy, bất cứ method nào gọi doOpenXML đều phải catch nó hoặc đánh dấu là sẽ throw ra exception của method nó gọi. Trong trường hợp này doParseXML gọi doOpenXML và quyết định throw ra IOException của doOpenXML. Đồng thời nó cũng throw thêm 1 exception là XMLParseException. Và method main gọi doParseXML chọn cách catch các exception của doParseXML có thể throw.

Unchecked exception:

public class MainCheckedAndUncheckedException {

	public static void main(String[] args) {
		printArray();
	}

	private static void printArray() {
		int[] array = new int[1];
		System.out.println(array[1]);
	}
}

Với đoạn code trên sẽ có 1 exception được throw ra mà không hề báo trước:

Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 1
at com.edward.tutorial.corejava.exception.MainCheckedAndUncheckedException.printArray(MainCheckedAndUncheckedException.java:12)
at com.edward.tutorial.corejava.exception.MainCheckedAndUncheckedException.main(MainCheckedAndUncheckedException.java:7)

Dù cho ta có đánh dấu method printArray sẽ throw ra ArrayIndexOutOfBoundsException thì IDE vẫn không báo lỗi khi hàm main gọi đến hàm printArray bởi vì ArrayIndexOutOfBoundsException là 1 unchecked exception

public class MainCheckedAndUncheckedException {

	public static void main(String[] args) {
		printArray();
	}

	private static void printArray() throws ArrayIndexOutOfBoundsException {
		int[] array = new int[1];
		System.out.println(array[1]);
	}
}

Checked và Unchecked Exception use cases

Vậy một câu hỏi đặt ra khi design API là khi nào một method sẽ throw checked exception, và khi nào sẽ throw unchecked exception.

Throw unchecked exception trong trường hợp chương trình bị sai về logic, không thể làm gì tiếp theo nếu gặp những lỗi đó, ví dụ như có 1 biến null hoặc không hợp lệ khiến toàn bộ đoạn chương trình phía sau không thể làm tiếp, ta sẽ throw NullPointerException hoặc IllegalArgumentException. Còn trong trường hợp những lỗi vẫn còn có thể handle được thì throw checked exception. Ví dụ như method open file có thể throw FileNotFoundException nhằm mục đích cảnh báo khi client gọi đến method này, cần phải handle trường hợp không tìm thấy file lúc đọc file. Đó không phải là lỗi logic chương trình mà là 1 ngoại lệ khác với kết quả mong muốn từ việc đọc file.

http://edwardthienhoang.wordpress.com/