Java 14

 

JEP 361: Switch Expressions

- Java 12-13 에서 preview feature 였음. Java 14 에서 standard 로 변경

String result = switch (day) {
            case "M", "W", "F" -> "MWF";
            case "T", "TH", "S" -> "TTS";
            default -> {
                if(day.isEmpty())
                    yield "Please insert a valid day.";
                else
                    yield "Looks like a Sunday.";
            }
 
        };

 

JEP 305: instanceof 패턴 매칭

- preview feature

- if (obj instanceof SomeType) 후 if 블럭에서 (SomeType) obj 캐스팅 불필요:

before:

if (obj instanceof SomeType) {
	SomeType someType = (SomeType) obj;
	someType.doSomething();
}

after:

if (obj instanceof SomeType) {
    obj.doSomething();
}

 

JEP 358: NullPointerException 메시지 개선

- 정확히 어디서 null 참조가 발생했는지 알기 쉽게 표시.

- 메서드 체이닝 코드 디버깅에 있어 특히 편해질 것으로 보임.

before:

String name = someInstance.getValue().toString();
 
//Stacktrace
Exception in thread "main" java.lang.NullPointerException
    at NullPointerExample.main(NullPointerExample.java:5)

after:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "SomeValue.toString()" because the return value of "something.getValue()" is null
    at NullPointerExample.main(NullPointerExample.java:4)

 

JEP 359: Records

- preview feature

- 순수 데이터만 담는 클래스.

- 키워드 class 대신 record 를 사용하며, 아래와 같이 선언함:

record Car(String name, String manufacturer) {}

- 컴파일 시 final 클래스가 되며, java.lang.Record 를 상속. (enum 과 유사.)

- 함께 선언한 필드는 모두 final이 되며, 값을 대입하는 public 생성자가 자동으로 생성됨:

public Car(String name, String manufacturer) {
	this.name = name;
	this.manufacturer = manufacturer;
}

- 필드의 getter 메서드도 자동으로 생성됨.

- toString, hashcode, equals 로 자동으로 오버라이딩하며, 필드 값을 기준으로 같은 결과를 반환. 

- 생성자에 사용된 필드 외에 다른 인스턴스 필드를 선언할 수 없음.

- 인스턴스 메서드 선언 가능.

- interface 구현 가능.

- static 필드, 메서드는 선언 가능.

- 생성자 오버로딩 가능.

- 자동 생성된 기본 생성자 변경 가능. 이 때 생성자 파라미터 생략 가능:

record Car(String name, String manufacturer) {
	public Car {	// 파라미터 생략 가능. name, manufacturer 이 숨겨져 있다.
    	// 파라미터 할당문 생략 가능. 컴파일러가 자동 생성.
    }
}

- java.lang.Class 에 isRecord, getRecordComponents 가 추가됨. isRecord는 이 클래스가 record 타입인지 확인하고, getRecordComponents는 record 필드를 가져옴.

 

JEP 368: Text Blocks

- preview feature (second preview)

- Java 13 에서 등장한 Text Blocks 에 새로운 이스케이프 2 개 추가

- \ (백슬래시) : 자동 줄바꿈을 방지함:

String inline = """
		1\
                2\
                3\
                """;
System.out.println(inline); // "123"

- \s: 공백을 유지함. Text Blocks 에서는 문자열이 자동으로 stripped되기 때문에, 기본적으로 앞뒤 공백이 제거됨. 공백을 유지하고 싶은 경우 사용.

 

JEP 343: Packing Tool (jpackage)

- incubator

- 자바 어플리케이션 패키징을 손쉽게 하기 위해 사용.

- 플랫폼에 맞는 패키징을 돕는다. (Linux: deb, rpm / macOS: pkg, dmg / Windows: msi, exe)

 

JEP 345: NUMA-Aware Memory Allocation for G1

- Non-Uniform Memory Access (NUMA) 는 멀티프로세싱 시스템에서의 멀티프로세서 클러스터링 아키텍처로, 각 프로세스가 독립적인 로컬 메모리를 보유하도록 하여 성능 향상을 도모한다. 프로세서와 그 프로세서의 메모리(로컬 메모리) 로 하나의 NUMA node를 구성하며, 프로세서가 자신의 node의 메모리에 빠르게 접근할 수 있다. 외부 node로의 접근은 상대적으로 느리며, 그 속도는 node의 거리가 멀수록 더 느리다.

- Java 14 에서는 G1이 NUMA를 인식하여 새로 메모리를 할당할 때 현재 쓰레드가 위치한 같은 NUMA node에 가용 공간이 있는지를 먼저 찾고, 없으면 가장 인접한 node를 검색하는 방식으로 NUMA 아키텍처의 성능 이점을 활용하도록 한다.

- 다음 파라미터로 활성화함:

+XX:+UseNUMA

- 위 파라미터를 지정하면 JVM이 초기화될 때 전체 NUMA nodes에 regions를 분포하도록 한다.

 

JEP 349: JFR Event Streaming

- JFR 이벤트를 수신할 수 있는 API 를 제공.

- in-process, out-of-process 어플리케이션 모두에 사용 가능.

- jdk.jfr.consumer 패키지 사용.

- CPU 사용률과 모니터 락 경합 이벤트를 10ms 주기로 수신하는 예시 코드:

try (var rs = new RecordingStream()) {
  rs.enable("jdk.CPULoad").withPeriod(Duration.ofSeconds(1));
  rs.enable("jdk.JavaMonitorEnter").withThreshold(Duration.ofMillis(10));
  rs.onEvent("jdk.CPULoad", event -> {
    System.out.println(event.getFloat("machineTotal"));
  });
  rs.onEvent("jdk.JavaMonitorEnter", event -> {
    System.out.println(event.getClass("monitorClass"));
  });
  rs.start();
}

 

JEP 352: Non-Volatile Mapped Byte Buffers

- java.nio.MappedByteBuffer 가 non-volatile memory (NVM) 의 파일을 로드 처리할 수 있도록 함.

 

JEP 364: ZGC on macOS

- experimental

- macOS에서 ZGC 지원.

- macOS에서 메모리 멀티 매핑 지원.

- 인접하지 않은 메모리 reservations 지원.

 

JEP 365: ZGC on Windows

- experimental

- Windows에서 ZGC 지원.

- Windows 10 지원.

- WIndows Server version < 1803 미지원.

 

JEP 370: Foreign-Memory Access API

- incubator

- 새로운 native memory 접근 API 추가.

- 자바 어플리케이션의 힙 메모리 사용은 메모리 효율성, (상대적으로)낮은 성능, GC 등의 이슈가 있음. 

- 이에 때에 따라서 외부 메모리(native memory)에 접근할 필요가 있는데, 기존 접근 방법은 ByteBuffer API, Unsafe API 두 가지가 있음.

- ByteBuffer API는 native memory 할당을 가능하게 하지만, 가용 메모리가 최대 2 기가라는 점과, 메모리 해제를 GC가 책임져야 한다는 한계가 있음. 때문에 잘못된 방법으로 API를 사용하면 메모리 릭이 발생할 수 있고 OOM으로 연결됨.

- Unsafe API는 메모리 관리에 굉장히 효율적일 수 있지만, 잘못 사용하면 JVM 크래시를 일으킬 수 있고, 표준 API가 아니라는 단점이 있음.

- Java 14 는 native memory 접근을 위한 세 가지 추상화를 제공: MemorySegment, MemoryAddress, MemoryLayout.

- MemorySegment: 힙 또는 native memory에 연속된 메모리 공간을 할당함. 다음과 같이 사용할 수 있음:

MemorySegment memorySegment = MemorySegment.allocateNative(200);  // 200 바이트의 native memory 할당.
MemorySegment memorySegment = MemorySegment.ofArray(new long[100]);  // 자바 힙 메모리 segment.
MemorySegment memorySegment = MemorySegment.ofByteBuffer(ByteBuffer.allocateDirect(200));  // buffer memory segment.

mapped memory file에도 사용할 수 있음. (mapped memory segment):

MemorySegment memorySegment = 
	MemorySegment.mapFromPath(Path.of("/tmp/memory.txt"), 200, FileChannel.MapMode.READ_WRITE);

 

memory segment는 현재 쓰레드에 묶임. 다른 쓰레드에 있는 memory segment에 접근하려면 acquire 메서드를 통해 접근 권한을 획득해야 함.

memory segment는 JVM 안정성을 위해 그 접근에 있어 두 가지 바운더리가 있음:

Spatial boundary: 공간적 경계. 접근 가능한 범위가 정해져 있어, 이 범위 밖의 메모리에 접근 시도하면 exception 발생.

Temporal boundary: 시간적 경계. 생성 및 사용되고, 더 이상 사용되지 않으면 closed된다. closed된 영역에 접근 시도하면 exception 발생.

 

- MemoryAddress: memory segment의 memory offset. 메모리의 데이터를 검색하거나 할 때 사용됨:

MemoryAddress address = MemorySegment.allocateNative(100).baseAddress();

- MemoryLayout: memory segment의 내용을 제공. 특히 메모리를 점유하는 요소의 사이즈를 제공하여 메모리가 요소에 어떤식으로 분산할지 정의할 수 있음.

int numberOfPoints = 10;
MemoryLayout pointLayout = MemoryLayout.ofStruct(
  MemoryLayout.ofValueBits(32, ByteOrder.BIG_ENDIAN).withName("x"),
  MemoryLayout.ofValueBits(32, ByteOrder.BIG_ENDIAN).withName("y")
);
SequenceLayout pointsLayout = 
  MemoryLayout.ofSequence(numberOfPoints, pointLayout);

- MemoryHandles: MemorySegment로 할당한 메모리를 사용함:

long value = 10;
MemoryAddress memoryAddress = MemorySegment.allocateNative(8).baseAddress();
VarHandle varHandle = MemoryHandles.varHandle(long.class, ByteOrder.nativeOrder());
varHandle.set(memoryAddress, value);
 
assertThat(varHandle.get(memoryAddress), is(value));

- 이 외에 다양한 MemoryLayouts가 존재함: ValueLayout, SequenceLayout, GroupLayout.

 

 

출처: 

https://www.journaldev.com/37273/java-14-features

https://dzone.com/articles/a-first-look-at-records-in-java-14

https://openjdk.java.net/jeps/349

https://www.baeldung.com/java-foreign-memory-access

'Java > Core' 카테고리의 다른 글

Java 13 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 11 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26

Java 13

 

JEP 355: Text Blocks

- preview feature

- String str = """ 문자열 """;

- 멀티라인 문자열을 더 보기 좋고 편하게 작성할 수 있음.

String textBlock = """
		This
		is
		a
		new
		feature,
		Text
		Block!""";
System.out.println(textBlock);
String inline = "\nThis\nis\anew\nfeature,\nText\nBlock!";
System.out.println(textBlock.equals(inline));

output:

This
is
a
new
feature,
Text
Block!
true

줄바꿈 문자가 자동으로 포함된다. 자바 코드로 json, html 텍스트를 작성할 때 아주 편리할 듯.

 

텍스트 블록용 String 메서드 추가

- formatted(Object ...args): String.format() 와 비슷한 기능. 텍스트블록에 사용됨.

- stripIndent(): 문자열 안의 모든 라인에 strip를 적용하여 앞 뒤 공백을 제거함.

- translateEscapes(): 연속된 이스케이프 문자를 변환 - ""\\t" => "\t"

 

JEP 354: Switch Expressions Enhancements

- preview feature

- yield 키워드:

switch(mode) {
	case "a", "b":
		yield 1;
	case "c", "d", "e":
		yield 2;
	default:
		yield -1;
};

- yield 는 값을 반환하고 switch를 빠져나감 (break)

- arrrow 도 여전히 사용 가능.

 

JEP 353: Socket API 재구현

- 신규 클래스 sun.nio.ch.NioSocketImpl 추가되어 java.net.PlainSocketImpl 을 대체함.

- NioSocketImpl 는 내부에서 synchronized 대신 java.util.concurrent 패키지의 locks를 사용함.

- 아래 아규먼트로 Socket API 사용 가능:

-Djdk.net.usePlainSocketImpl

 

JEP 350: Dynamic CDS Archive

- JVM 옵션을 통해 CDS를 더 편하게 사용 가능:

$ java -XX:ArchiveClassesAtExit=my_app_cds.jsa -cp my_app.jar
$ java -XX:SharedArchiveFile=my_app_cds.jsa -cp my_app.jar

 

JEP 351: ZGC:Uncommit Unused Memory

- ZGC가 사용하지 않는 힙 메모리를 OS에 반환하도록 함.

 

static java.nio.file.FileSystems.newFileSystem 메서드 추가

- newFileSystem(Path, ClassLoader)

- newFileSystem(Path, Map<String, ?>)

- newFileSystem(Path, Map<String, ?>, ClassLoader)

 

DOM and SAX Factories with Namespace Support

- newDefaultNSInstance()

- newNSInstance()

- newNSInstance(String, ClassLoader)

 

 

출처: 

https://www.journaldev.com/33204/java-13-features

'Java > Core' 카테고리의 다른 글

Java 14 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 11 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26

Java 12

 

언어 상 변화

Switch Expressions (JEP 325)

- preview feature

before:

int numLetters;
switch (day) {
	case MONDAY:
	case FRIDAY:
	case SUNDAY:
		numLetters = 6;
		break;
	case TUESDAY:
		numLetters = 7;
		break;
	case THURSDAY:
	case SATURDAY:
		numLetters = 8;
		break;
	case WEDNESDAY:
		numLetters = 9;
		break;
	default:
		throw new IllegalStateException("Huh? " + day);
}

after:

int numLetters = switch (day) {
	case MONDAY, FRIDAY, SUNDAY -> 6;
	case TUESDAY -> 7;
	case THURSDAY, SATURDAY -> 8;
	case WEDNESDAY -> 9;
	default -> throw new IllegalStateException("Huh? " + day);
};

 

라이브러리 변화

Teeing Collectors

- Collectors.teeing(Collector, Collector, BiFunction)

- 1, 2 번 아규먼트 컬렉터의 연산 결과를 BiFunction 아규먼트로 넘겨 BiFunction 이 최종 컬렉팅을 수행한다:

double mean = Stream.of(1, 2, 3, 4, 5)
                .collect(Collectors.teeing(
                        summingDouble(i -> i),
                        counting(),
                        (sum, n) -> sum / n));

System.out.println(mean); // 3

 

InputStream.skipNBytes(n)

- 정확히 n 만큼의 바이트를 스킵함.

- n <= 0 이면 스킵하지 않음.

 

java.lang.constant 패키지 추가

 

java.lang.Character

- 체스 심볼 추가

- 마야 숫자 표현 추가

- 소그디니아어 추가

 

java.lang.Class 메서드 추가

- arrayType(): 해당 클래스의 array type 클래스를 반환:

jshell> "foo".getClass().arrayType()
$15 ==> class [Ljava.lang.String;

- componentType(): 기존 getComponentType()과 동일?

- descriptorString(): java.lang.Class에 TypeDescriptor 인스페이스 구현이 추가되어 이 메서드를 오버라이딩함. 현재 getName()과 동일한 결과를 반환함.

 

java.lang.String 메서드 추가

- indent(n): 들여쓰기 수행. 아래 과정으로 처리된다:

Step 1. String.lines() 를 통해 라인을 쪼갠다.

Step 2. n > 0 이면 라인마다 n 만큼의 공백을 추가한다. n < 0 이면 n 라인마다 만큼의 공백을 제거한다. 공백이 없으면 제거하지 않는다. n == 0 이면 그냥 둔다.

Step 3. 라인을 모두 합친다. (줄바꿈 문자열은 유지한다.)

 

- transform(Function<String>): 문자열에 Function을 실행한 결과를 반환한다:

hello".transform(input -> input + " world!"); // "hello world!"

 

java.net.SecureCacheResponse, java.net.ssl.HttpsConnection 메서드 추가

- Optional<SSLSession> getSSLSession(): 현재 커넥션의 SSL 세션을 반환.

 

long java.nio.files.Files.mismatch(Path, Path)

- 두 파일 내용을 바이트로 비교하여 처음 차이가 발견된 바이트의 위치를 반환한다. 차이가 발견되지 않으면 -1L을 반환한다.

 

java.text.CompactNumberFormat

- NumberFormat의 서브클래스로, 1,000,000 => 1M 으로 변환하는 등의 포맷팅을 수행한다.

 

java.util.concurrent.CompletionStage 메서드 추가

- ComplitionStage<T> exceptionallyAsync(Function<Throwable, ? extends T>): CompletableFuture.supplyAsync() 에서 발생한 에러를 비동기로 핸들링한다.

- ComplitionStage<T> exceptionallyAsync(Function<Throwable, ? extends T> Executor executor): 기능은 위와 같음. 비동기 에러 핸들링을 수행할 Executor를 지정한다.

- ComplitionStage<T> exceptionallyCompose(Function<Throwable, ? extends CompletionStage<T>>): CompletableFuture.supplyAsync() 에서 에러가 발생하면 Function 을 수행한다. 이 Function 에서 반환한 CompletableStage 는 다음 수행 Future 가 된다. 

- ComplitionStage<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>>): 기능은 위와 같음. 비동기로 수행한다.

- ComplitionStage<T> exceptionallyComposeAsync(Function<Throwable, ? extends CompletionStage<T>>, Executor): 기능은 위와 같음. 이 로직을 수행할 Executor를 지정한다.

 

javax.crypto.Cipher.toString()

- 암호화 모드, 알고리즘 등에 대한 정보를 제공하도록 변경됨.

 

javax.naming.ldap.spi 패키지 클래스 두 개 추가

- LdspDnsProvider: LDAP DNS 룩업을 위한 서비스 프로바이더.

- LdapDnsProviderResults: LDAP DNS 룩업 결과를 캡슐화.

 

File[] javax.swing.filechooser.FileSystemView.getChooserShortcutPanelFiles()

- 스윙 파일 선택기 창의 숏컷 패널의 파일(디렉토리) 정보를 java.io.File 배열로 반환

 

JVM 변화

JEP 189: Shenandoah

- OpenJDK 에 포함됨

 

JEP 344: Abortable Mixed Collections for G1

- G1 GC는 힙 공간을 2048개의 regions로 나누고, 각 영역은 youg과 old 로 논리적으로 구분된다. G1 GC는 가비지 컬렉션을 수행하기 위해 수행 대상 regions를 선택하는데 (collection set), young과 old가 섞이게 되는 mixed collections에서 old regions가 너무 많이 잡히게 되면 pause time이 길어져 목표치를 초과하게 될 수 있다. 이를 방지하기 위해서는 G1 GC가 collection set을 만드는 과정에서 잘못된 수의 regions을 반복적으로 select하는 때를 감지하여 실제 가비지 컬렉션 과정 중간에 작동을 취소할 수 있게끔 해야 한다 (aborable).

 

위 목표를 실현하기 위해 Java 12 의 G1 GC는 잘못된 수의 regions가 반복적으로 select됨을 감지하면 더욱 점진적인 mixed collections 과정을 취한다: collection set을 mandatory part, optional part 둘로 나눈다. mandatory part는 young regions와 같이 G1 GC가 점진적 처리를 할 수 없는 영역으로 구성하지만, 효율성을 위해 old regions도 포함할 수 있다.

그리고 나머지는 old regions로만 구성된 optional part가 된다. 이 과정의 결과로 collection set은, 예를 들어 80%의 mandatory part, 20%의 optional part와 같이 나뉘게 된다.

 

우선 mandatory part의 가비지 컬렉션을 마치고 optional part에 대해서는 훨씬 더 세분화된 방법을 취한다. pause time 여유가 남아 있다면 그 시간에 비례하여 old regions를 처리하는데, 최대 한 번에 한 old region씩 처리한다. 처리 도중 남은 시간이 없다면 처리 중인 region까지만 작업을 마치고 다음 가비지 컬렉션을 중단한다(abort).

 

mandatory part을 다시 구성할 때 까지, 위 과정이 반복되면서 optional part는 점점 작아지게 된다. 그러다 다시 collection set을 나누게 되면 mandatory part와 optional part를 새로 만든다.

 

JEP 346: Promptly Return Unused Committed Memory from G1

- 기존 G1 GC에는 시간에 따른 JVM 메모리 릴리즈가 없었다. 기존 G1 GC가 OS에 메모리를 반환하는 때는 full GC or concurrent GC cycle 이다. 그런데 G1 GC는 full GC를 최대한 피하도록 설계되었고, concurrent GC cycle은 힙 메모리 사용량과 할당 작업에서만 작동하기 때문에, 결과적으로 기존 G1 GC는 OS에 메모리를 잘 반환하지 않는다. 그리고 이는 사용 자원에 따라 요금을 부과하는 클라우드 환경에서 불필요한 비용을 초래한다. 어플리케이션이 놀고 있는 때에도 메모리를 잡고 있으니, 사용하지 않는 물건에 대해 요금을 계속 지불하게 되는 것이다.

 

이 문제를 완화하기 위해 Java 12 의 G1 GC는 적절한 시간 안에서 어플리케이션이 사용되지 않는다고 판단되면 사용하지 않는 메모리 일부를 OS에 반환하여 JVM 힙 크기를 조정하도록 한다.

 

JDK 새로운 기능

JEP 230: 마이크로벤치마킹 슈트

- 성능 측정 도구인 Java Microbenchmarking Harness (JMH) 가 OpenJDK에 포함되었다. 

 

JEP 341: Default CDS 아카이브

- 상용 Oracle JDK 의 기능이었던 CDS가 OpenJDK에 포함되었다. CDS를 사용하기 위해 lib/server 디렉토리에 classes.jsa 파일이 생성된다. 

 

 

출처:

https://dzone.com/articles/39-new-features-and-apis-in-jdk-12

https://www.baeldung.com/java12-string-api

https://openjdk.java.net/jeps/344

'Java > Core' 카테고리의 다른 글

Java 14 간략히 정리  (0) 2020.07.16
Java 13 간략히 정리  (0) 2020.07.16
Java 11 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26

Java 11

 

새로운 String 메서드 추가

- strip(): 문자열 앞, 뒤의 공백 제거.

- stripLeading(): 문자열 앞의 공백 제거.

- stripTrailing(): 문자열 뒤의 공백 제거.

 

trim() 과의 차이점은, trim() 은 U+0020 이하의 값만을 공백으로 인식하여 제거한다 (tab, CR, LF, 공백). 하지만 유니코드에서는 이 외에 다양한 공백 문자가 존재하는데, 이를 처리하기 위해서는 기존에는 Character.isWhitespace(int) 를 사용해야 했다. Java 11 부터는 strip() 으로 편하게 처리할 수 있다.

 

그리고 성능도 수 배 빠른 것으로 알려짐.

 

- isBlank(): 문자열이 비어있거나 공백만 포함되어 있을 경우 true 를 반환한다. 즉, String.trim().isEmpty() 호출 결과와 같다.

 

- lines(): 문자열을 라인 단위로 쪼개는 스트림을 반환.

- repeat(n): 지정된 수 만큼 문자열을 반복하여 붙여 반환:

String str = "ABC";
String repeated = str.repeat(3);	// "ABCABCABC"

 

java.nio.file.Files 클래스 유틸 메서드 추가

- Path writeString(Path, String, Charset, OpenOption): 파일에 문자열을 작성하고 Path로 반환한다. 파일 오픈 옵션에 따라 작동 방식을 달리하며, charset을 지정하지 않으면 utf-8 이 사용된다. (오버로딩 메서드로 writeString(Path, String, OpenOption) 존재.)

- String readString(Path, Charset): 파일 전체 내용을 읽어서 String으로 반환하고, 파일 내용을 모두 읽거나 예외가 발생하면 알아서 close 한다. charset을 지정하지 않으면 utf-8 이 사용된다. (오버로딩 메서드로 readString(Path) 존재.)

- boolean isSameFile(Path, Path): 두 Path 가 같은 파일을 가리키면 true, 아니면 false 를 반환한다. 파일이 실제로 존재하지 않아도, Path 를 기준으로 해서 같은 위치면 true 로 판단한다.

 

Pattern.asMatchPredicate()

- Java 8 의 asPredicate는 matcher().find() 를 사용하는 것에 반해, asMatchPredicate() 는 matcher().match() 를 사용하는 Predicate를 반환한다.

 

Predicate.not(Predicate)

- 인자로 받은 Predicate의 부정형 Predicate를 반환한다.

 

람다 파라미터로 var 사용:

(var n1, var n2) -> n1 + n2

- Java 8 에 등장했으나 Java 10 에서 사라졌다가 Java 11 에서 복귀한 기능.

- 람다는 타입을 스킵할 수 있는데 이걸 사용하는 이유는, @Nullable 등의 어노테이션을 사용하기 위해 타입을 명시해야 할 때.

- var 를 사용하려면 괄호를 써야하며, 모든 파라미터에 사용해야 하고, 다른 타입과 혼용하거나 일부 스킵은 불가능함:

(var s1, s2) -> s1 + s2 // 안 됨. s2 에도 var 필요.
(var s1, String y) -> s1 + y // 안 됨. String 과 혼용 불가.

var s1 -> s1 // 안 됨. 괄호 필요.

 

Optional.isEmpty()

- Optional이 비어있을 때 true 반환.

 

TimeUnit.convert(Duration)

TimeUnit c = TimeUnit.DAYS;
c.convert(Duration.ofHours(24));	// 2
c.convert(Duration.ofHours(72));	// 3

 

Nest-Based Access Control (JEP 181)

- Java 10 까지 nested 클래스에서 자신, 혹은 outer 클래스의 private 멤버에 리플렉션을 통한 접근을 시도하면 IllegalAccessException 이 발생했고, 이를 피하기 위해 setAccessible(true) 을 호출해야만 했음.

- Java 11 부터는 setAccessible 없이 private 멤버를 호출할 수 있음.

- java.lang.Class 에 다음 메서드들이 추가됨.

- getNestHost(): nested 클래스에서 호출하면 자신을 감싸고 있는 outer 클래스를 반환하고, outer 클래스에서 호출하면 자신을 반환.

- boolean isNestmateOf(Class): 자신이 아규먼트로 받은 Class의 nested 클래스일 때 true 를 반환함.

- Class[] getNestMembers(): 자신을 포함하여 중첩 관계에 있는 모든 클래스를 배열로 반환함. (outer, siblings)

 

Epsilon Garbege Collector (No-Op GC, JEP 318)

- JVM으로 하여금 메모리 할당을 관리하지만, 사용된 메모리를 재사용하지 않도록 함. 메모리를 다 사용하면 OutOfMemory가 발생하고 JVM은 셧다운된다.

- 어플리케이션 테스트에 사용됨. GC는 어플리케이션과 함께 작동하며, 오버헤드가 있어 어플리케이션 성능에 영향을 준다. No-OP GC를 적용하여 GC를 배제함으로써 순수 어플리케이션의 성능, 메모리 부하 등을 테스트할 수 있도록 한다. GC 적용 시의 성능과 비교하여 GC의 영향도를 측정할 수 있다.

- 짧은 시간 수행하고 종료되는 어플리케이션에 사용됨. 간단히 작동하고 마치는, 메모리 부하가 크게 염려되지 않는 어플리케이션에 적절하게 사용될 수 있음.

- 아래 아규먼트를 사용하여 활성화한다:

-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

 

Dynamic Class-File Constants (JEP 309)

 

Java Flight Recorder  (JEP 328)

- 상업용 OracleJDK 에 제공되던 JFR이 OpenJDF에 포함된다.

- Java 어플리케이션으로부터 프로파일링, 어플리케이션 진단 데이터 등을 얻을 수 있음.

- 성능 오버헤드가 1% 미만으로 알려져 있어, 운영 환경에서 사용할 수 있음.

 

HTTP Client (JEP 321)

- Java 표준 HTTP 클라이언트 API.

- 그간 HTTP 통신을 위해 사용된 코드보다 성능이 개선됨.

- HTTP/1.1, HTTP/2, WebSocket을 지원한다. 

 

java 파일 실행 (JEP 330)

- javac를 통한 컴파일 없이 java 파일을 실행할 수 있음:

$> java HelloWorld
Hello world!!

- java 파일에 main 메서드가 존재해야 함.

- 다음과 같이 클래스패스 지정:

java --class-path=/myclasspath ExecutionTest.java

- 클래스패스에 동일한 이름의 클래스가 존재하면 에러 발생. (java 확장자 무시.)

 

 

기타 제거된 기능 및 옵션

com.sun.awt.AWTUtilities 클래스

Lucida 폰트 (Oracle JDK)

appletviewer Launcher

javax.imageio JPEG 플러그인 alpha 이미지 지원 X

sun.misc.Unsafe.defineClass

Thread.destroy()

Thread.stop(Throwable)

JVM-MANAGEMENT-MIB.mib

SNMP 에이전트

JavaFX (Oracle JDK)

Java EE (JAX-WS, JAXB, JAF, Common Anotations) (JEP 320)

CORBA (JEP 320)

 

deprecated된 기능 및 옵션

ThreadPoolExecutor는 Finalization에 의존성을 갖지 않도록 (should not)

Nashorn 자바스크립트 엔진 (JEP 335)

-XX+AggressiveOpts

Pack200 툴 및 API (JEP 336)

스트림 기반 GSSContext 메서드

 

 

출처:

https://dzone.com/articles/features-of-java-11

https://www.journaldev.com/24601/java-11-features

https://www.geeksforgeeks.org/java-11-features-and-comparison/

 

 

'Java > Core' 카테고리의 다른 글

Java 13 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26
람다  (0) 2020.01.05

Java 10

 

var 키워드

- 지역변수에만 사용 가능.

- 컴파일 타임에 타입이 확실한 곳에만 사용 가능.

- 컴파일 타임에 타입 추정(type inference)이 적용되어, 바이트코드는 이전과 동일하게 생성.

 

Unmodifiable View Collections

- 컬렉션을 wrapping하여 변경 불가능한 컬렉션을 만든다.

- immutable 과는 다름. 직접 데이터를 가지고 있지 않고, 원본 인스턴스의 view 로서 작동한다. 원본 인스턴스에 요소가 추가/삭제/변경되면 이를 래핑한 unmodifiable collections 도 변경되어 보여진다. 글자 그대로 VIEW.

List unmodifiable = Collections.unmodifiableList(existingList);

 

Creating Immutable Collections 

- List, Set, Map 에 copyOf(...) 등장. 얉은 복사를 수행하여 immutable collection을 반환한다.

List immutableCopied = List.copyOf(existingList);

- 공간 효율성이 다르다. 아래 코드에서, HashSet 은 내부의 HashMap 을 포함하여 6개의 인스턴스를 가진다:

Set<String> set = new HashSet<>(3);   // 3 buckets
set.add("silly");
set.add("string");
set = Collections.unmodifiableSet(set);

하지만 아래 코드는 2개 필드를 가진 인스턴스를 1개 생성한다. heap 사용률을 줄일 수 있다:

Set<String> set = Set.of("silly", "string");

 

Immutable Collectors

- 스트림의 컬렉터로 immutable collection 을 생성하는 컬렉터가 추가됨:

   Set<Item> immutableSet =
      sourceCollection.stream()
                      .map(...) 
                      .collect(Collectors.toUnmodifiableSet());

G1GC 개선

- Java 9 에서 디폴트 GC 알고리즘으로 채택된 G1GC 의 full gc 방식을 개선.

- Full GC 시 전체 프로세싱을 병렬로 수행하여 성능 향상.

 

CDS (Class Data Sharing) 옵션 추가

- Java 5 에서 도입된 기존 CDS 는 부트스트랩 클래스로더의 대상 클래스만을 쉐어링한다.

- 다음 아규먼트를 통해 시스템 클래스로더와 플랫폼 클래스로더로 쉐어링하도록 설정 가능:

-XX:+UseAppCDS

- 어플리케이션 클래스를 쉐어링하도록 설정할 수 있음:

Step 1. 쉐어링 대상 클래스 지정:

java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=myapp.lst \
  -cp $CLASSPATH $MAIN_CLASS

Step 2. CDS 아카이브 생성:

java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=myapp.lst \
  -XX:SharedArchiveFile=myapp.jsa \
  -cp $CLASSPATH

Step 3. 어플리케이션 실행:

java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa \
    -cp $CLASSPATH $MAIN_CLASS

 

JIT 컴파일러 관련

- 기존 JIT 컴파일러는 C++ 로 작성되어, 변경에 어려움이 있음

- 순수 자바로 JIT 컴파일러를 작성 가능하도록 하는 JVM Compiler Interface (JVMCI) 등장.

- 그 결과로, 순수 자바로 작성된 Graal 등장.

- 아직 실험적인 단계여서, 다음 아규먼트를 설정할 때만 작동:

-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler

 

Thread-Local 핸드셰이크

- 기존 JVM은 모든 쓰레드의 스택트레이스를 얻거나 GC를 수행하기 위해서는 한 모든 쓰레드를 정지시켜야 했음(STW)

- STW 의 이유는, JVM이 작업을 마친 뒤 쓰레드들이 하던 작업을 그대로 다시 수행하도록 하기 위해 글로벌 세이프포인트를 생성하기 위함. 세이프포인트가 있어야 쓰레드가 다시 작동할 컨텍스트를 알 수 있고, 그래야 쓰레드를 멈출 수 있음.

- Java 10 부터 JVM은 임의의 숫자의 쓰레드 세이프포인트를 생성할 수 있음. 고로, 한 번에 한 쓰레드만 멈출 수 있게 됨.

 

컨테이너 인식

- 전까진 JVM은, CPU, 메모리 등의 자원을 호스트 OS 에서 쿼리했음.

- Java 10 부터는 JVM이 도커 컨테이너 안에서 작동하는 경우, 도커 컨테이너에 할당된 자원을 쿼리할 수 있게 됨.

- 예로, Java 9 까지는 호스트 OS 의 가용 메모리가 2G 이고, JVM이 작동하는 컨테이너에는 0.5G 만 할당되어 있는 환경에서 Java는 메모리를 2G 로 쿼리한다. Java 10 부터는 도커의 컨테이너 컨트롤 그룹에서 자원을 쿼리할 수 있도록 하여 컨테이너 환경에서의 실제 가용 자원을 정확하게 얻을 수 있음.

- 컨테이너 환경에서 힙메모리와 프로세서 수를 지정하는 아규먼트가 존재함:

-XX:+UseCGroupMemoryLimitForHeap 
-XX:ActiveProcessorCount=2

 

OpenJDK 의 SSL 관련

 

 

출처: 

https://dzone.com/articles/whats-new-in-java-10

 

'Java > Core' 카테고리의 다른 글

Java 13 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 11 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26
람다  (0) 2020.01.05

 

IO

- NIO가 나오면서 자바의 기존 IO 방식은 OIO(Old I/O)라고도 불림.

- *InputStream, *OutputStream, *Reader, *Writer...

- 전통적인 blocking call 방식.

- 때문에 FD(소켓, 파일...) 당 하나의 쓰레드가 필요함.

- 때문에, 동시 요청이 자주 발생하는 어플리케이션의 경우 필연적으로 쓰레드 풀을 사용하게 됨.

 

 

NIO

- New I/O 로, 자바 1.4에서 등장.

- 주요 요소: Buffer, Charset, Channel, Selector.

- Buffer: NIO의 데이터 저장 컨테이너로, 다이렉트 버퍼, 논 다이렉트 버퍼(힙 버퍼)로 나뉨. 다이렉트 버퍼는 네이티브 메모리를 사용하고, 논 다이렉트 버퍼는 JVM의 힙 메모리를 사용함.

- Channel: 데이터가 오고 가는 양방향 통로.

- Selector: non-blocking, 이벤트 방식으로, 지정한 채널에 발생한 이벤트를 수신하여 이벤트 유형에 맞는 동작을 처리할 수 있음. 

- 결정적으로, OIO에서는 다수의 요청을 받아들이기 위해 많은 수의 쓰레드를 필요로 했지만, NIO에서는 Selector를 조회하는 하나의 쓰레드만으로 다수의 요청을 커버할 수 있음. 물론 요청의 성격에 따라 별도의 처리 쓰레드가 필요할 수 는 있다.

- 자바 6 부터는 epoll을 지원하여, 런타임 os가 리눅스 커널 2.6 이상이라면 epoll을 디폴트로 한다. poll을 사용하려면 아래와 같이 시스템 프로퍼티로 제어 가능함.

System.setProperty("java.nio.channels.spi.SelectorProvider", "sun.nio.ch.PollSelectorProvider");

- 이렇게, NIO는 os specific하다. os의 기능을 차용하여, 아래와 같이 런타임 os에 따라 동작을 달리한다.

Windows: select

Mac OS: Kqueue

리눅스 커널 2.6+: epoll

솔라리스: poll

 

 

NIO2

- 그냥 NIO로 통틀어 말하기도 함. 자바 1.7에서 등장. 네트워킹 I/O에는 마이너한, 파일 I/O에는 메이저한 변화가 있었음.

- Async* 시리즈의 등장으로, 비동기 콜백 방식의 I/O를 지원함.

'Java > Core' 카테고리의 다른 글

Java 13 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 11 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
람다  (0) 2020.01.05

람다와 익명클래스

 

람다와 익명클래스의 this 바인딩은 다르다. 람다의 this는 자신을 둘러싼 인스턴스를 참조하고, 익명클래스는 자기 자신의 인스턴스를 참조한다.

 

익명클래스의 생성과 동작 방식은 컴파일타임에 결정되지만, 람다는 런타임에 실제 호출 시 결정된다(invokedynamic).

 

컴파일타임에서, 익명클래스는 '클래스명$1' 의 형태로 개별 클래스파일이 생성되지만, 람다의 클래스파일이 따로 생성되지 않는다. 이는 람다의 경우 JVM이 클래스파일을 로드하기 위한 동작이 필요치 않음을 의미한다(-Djdk.internal.lambda.dumpProxyClasses=<dir> 을 통해 람다로 생성되는 동적 클래스를 파일로 저장할 수는 있다).

 

런타임에서, 익명클래스는 실행 시 마다 익명클래스의 인스턴스를 생성하는 과정을 거친다. 람다는 이 과정을 거치치 않는다. 람다는 JVM의 invokedynamic 연산을 통해 동적으로 생성된다(후에 private static 메서드로 풀어지고, 실행된다).

 

 

람다와 클로저

 

모든 클로저는 람다이지만, 모든 람다가 클로저는 아니다.

 

람다가 자신의 블록 밖의 변수(외부 변수)에 접근하면(capture), 이는 클로저이다(클로저는 자바 1 에서부터 익명클래스의 형태로 이미 존재해왔다).

 

'Java > Core' 카테고리의 다른 글

Java 13 간략히 정리  (0) 2020.07.16
Java 12 간략히 정리  (0) 2020.07.15
Java 11 간략히 정리  (0) 2020.07.15
Java 10 간략히 정리  (0) 2020.07.15
IO, NIO, NIO2  (0) 2020.02.26

+ Recent posts