Java8  Function과 Stream을 이용한 객체 복사 테스트 예제이다. 


List 값 비교는 Lamda를 사용하였다. 



import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.junit.Assert;
import org.junit.Test;
import static org.hamcrest.Matchers.*;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;


public class ConvertObjectTest {

Function<OneMember, OnePerson> convertFunction = new Function<OneMember, OnePerson>() {
public OnePerson apply(OneMember member) {
return new OnePerson(member.id, member.name);
}
};

@Test
public void convertObjectWithFunctionTest() {
OneMember member = new OneMember(1, "Samuel");
OnePerson person = convertFunction.apply(member);
Assert.assertEquals(member.name, person.name);
}

@Test
public void convertObjectListWithFunctionTest() {
OneMember samuel = new OneMember(1, "Samuel");
OneMember daisy = new OneMember(2, "Daisy");
OneMember matt = new OneMember(3, "Matt");
ImmutableList<OneMember> immutableMemberList = ImmutableList.of(samuel, daisy, matt);

List<OnePerson> personList = immutableMemberList.stream()
.map(convertFunction)
.collect(Collectors.<OnePerson>toList());

personList.sort((OnePerson h1, OnePerson h2) -> h1.id.compareTo(h2.id));
Assert.assertThat(personList.get(0), equalTo(new OnePerson(1, "Samuel")));
Assert.assertThat(personList.get(1), equalTo(new OnePerson(2, "Daisy")));
Assert.assertThat(personList.get(2), equalTo(new OnePerson(3, "Matt")));
}
}

class OneMember {
public Integer id;
public String name;
public OneMember(int id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

@Override
public boolean equals(Object obj) {
OneMember anotherMember = (OneMember) obj;
if (this.id == anotherMember.id && this.name.equals(anotherMember.name)) {
return true;
}
return false;
}
}

class OnePerson {
public Integer id;
public String name;

public OnePerson(int id, String name) {
this.id = id;
this.name = name;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

@Override
public boolean equals(Object obj) {
OnePerson anotherPerson = (OnePerson) obj;
if (this.id == anotherPerson.id && this.name.equals(anotherPerson.name)) {
return true;
}
return false;
}
}



위의 코드 중 일부를 Java8 람다 스타일로 변경할 수 있다.


1) Function을 람다 표현식으로 변경

Function<OneMember, OnePerson> convertFunction = new Function<OneMember, OnePerson>() {
public OnePerson apply(OneMember member) {
return new OnePerson(member.id, member.name);
}
};

---> 


Function<OneMember, OnePerson> convertFunction = member -> new OnePerson(member.id, member.name);


2) Guava의 ImmutableList를 Streams.of로 변경

ImmutableList<OneMember> immutableMemberList = ImmutableList.of(samuel, daisy, matt);

List<OnePerson> personList = immutableMemberList.stream()
.map(convertFunction)
.collect(Collectors.<OnePerson>toList());

--->

List<OnePerson> persons = Stream.of(samuel, daisy, matt)
.map(convertFunction)
.sorted(comparing(onePerson -> onePerson.id))
.collect(toList());




Posted by '김용환'
,


jvm에 dns 서버로부터 domain 정보 저장에 대한 cache 정책(TTL)을 '초단위'로 줄 수 있다.



java -Dsun.net.inetaddr.ttl=<값>



통신, DB같이 failover 를 염두한 애플리케이션에서는 'DNS TTL 캐쉬'는 반드시 써야 한다. 디폴트 값도 jvm마다 다를 수 있다.

-1 의 값을 주면, 캐쉬를 계속(forever)하기 때문에 잘 쓰지 않는다. TTL 값을 0 또는 적은 값으로 주는 것이 좋다.




JVM 문서를 살펴본다. sun.net.inetaddr.ttl 에 대한 디폴트 설정은 OS와 JVM 에 의존을 가지고 있다.



open jdk 7 source를 보면, sun.net.inetaddr.ttl 의 디폴트 값은 30초이다. 음수는 영원히 캐쉬함을 의미한다. 0으로 설정가능하다.

http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/net/InetAddressCachePolicy.java





이외에, 

공식 문서로는 sun.net.inetaddr.ttl 과 달리 자바의 security 설정 파일에 관련 설정이 networkaddress.cache.ttl 이 있다.

https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html#nct


networkaddress.cache.ttl

Specified in java.security to indicate the caching policy for successful name lookups from the name service.. The value is specified as integer to indicate the number of seconds to cache the successful lookup.

A value of -1 indicates "cache forever". The default behavior is to cache forever when a security manager is installed, and to cache for an implementation specific period of time, when a security manager is not installed.


(positive lookup을 의미)


-1의 값에 대해서는 명확히 상세하고 있지만, 디폴트 값에 대해서는 security manager와 구현에 따라 결정된다고 되어 있다. 


windows64, java8에서는 디폴트가 30이라는 얘기가 있긴 하지만, JVM 디폴트가 명세하지 않았기에 JVM 시작할 때 security configuration 설정에 명확히 설정하면 좋을 수는 있지만., 실제 사용할 때 JVM이 뜨기 전 (Security Manager가 실행되기 전)에 소켓이 초기화될 수 있기 때문에, 사실상 크게 의미가 없을 수 있다.


비슷한 사례는 여러 블로그에서도 발견될 수 있다.

https://support.stormpath.com/hc/en-us/articles/203697356-I-can-t-connect-to-the-Stormpath-REST-API-Is-the-server-down-



* 참고로, 

앞의 oracle 문서를 더 자세히 보면, 프러퍼티 하나가 더 추가된 것을 볼 수 있다. lookup의 실패에 대한 cache 정책도 추가할 수 있다. 디폴트가 10이니, 안써도 무관할 듯 싶다.


networkaddress.cache.negative.ttl (default: 10)
Specified in java.security to indicate the caching policy for un-successful name lookups from the name service.. The value is specified as integer to indicate the number of seconds to cache the failure for un-successful lookups.

A value of 0 indicates "never cache". A value of -1 indicates "cache forever".


(negative lookup을 의미)

(구) sun.net.inetaddr.negative.ttl







Posted by '김용환'
,


elasticsearch에서 필드의 색인 매핑(index mapping)시 3 개의 옵션을 넣을 수 있다.


- no : 색인되지 않음

- not_analyzed : 색인은 되나 토큰 추출은 하지 않는다.

- analyzed : 색인은 되나, 토큰 추출을 한다. 



 'Thank you, mother'  토큰을 입력한다면, 다음과 같이 나누어질 수 있다.

색인 매핑 값

Analyzer

토큰

no

색인 하지 않음

토큰 없음

not_analyzed

KeywordAnalyzer (exact 매칭)

[Thank you, mother]

analyzed

StandardAnalyzer (공백과 구두점으로 토큰을 추출, 소문자로 변환)


[thank, you, mother]






출처 :

https://www.elastic.co/guide/en/elasticsearch/guide/master/mapping-intro.html


https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-keyword-analyzer.html


https://www.elastic.co/guide/en/elasticsearch/guide/master/standard-analyzer.html

https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html


Posted by '김용환'
,


Java8에서 추가된 Date와 Time 객체를 이용한 테스트 예제를 사용해보았다.

import org.junit.Test;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Locale;

public class Java8LocalDate {

@Test
public void localDateTest() {
System.out.println();
LocalDate today = LocalDate.now();
System.out.println(today);

int year = today.getYear();
int month = today.getMonthValue();
int day = today.getDayOfMonth();
System.out.println(year + "." + month + "." + day);

LocalDate christMasDate = LocalDate.of(2015, 12, 25);
System.out.println(christMasDate);

LocalDate anotherDate = LocalDate.of(2015, 12, 25);
if(christMasDate.equals(anotherDate)) {
System.out.printf("same day : %s\n", anotherDate);
}

YearMonth yearMonthNow = YearMonth.now();
System.out.println("yearMonth : " + yearMonthNow);

MonthDay birthday = MonthDay.of(christMasDate.getMonth(), christMasDate.getDayOfMonth());
System.out.println("monthday : " + birthday);
MonthDay MonthDayNow = MonthDay.from(today);
if (MonthDayNow.equals(birthday)) {
System.out.println("Today is birthday.");
} else {
System.out.println("Today is not birthday");
}

LocalDate christMasEveDate = LocalDate.of(2015, 12, 24);
System.out.println(christMasEveDate.isBefore(christMasDate)); // true


System.out.println("1 week after : " + today.plus(1, ChronoUnit.WEEKS));
System.out.println("1 day after : " + today.plus(1, ChronoUnit.DAYS));
System.out.println("1 century after : " + today.plus(1, ChronoUnit.CENTURIES));
System.out.println("1 year after : " + today.plus(1, ChronoUnit.YEARS));

System.out.println("leap year : " + today.isLeapYear());
}

@Test
public void localTimeTest() {
System.out.println();
LocalTime time = LocalTime.now();
System.out.println("time : " + time);
System.out.println("2 hours after : " + time.plusHours(2));
System.out.println("3 hours before : " + time.minusHours(2));
}

@Test
public void clockTest() {
System.out.println();
Clock clock = Clock.systemUTC();
System.out.println("Clock : " + clock);
System.out.println("Clock (zone) : " + clock.getZone());

Clock laClock= Clock.system(ZoneId.of("America/Los_Angeles"));
System.out.println("LA Clock : " + laClock);

}

@Test
public void periodTest() {
System.out.println();
LocalDate startLocatDate = LocalDate.of(2015, Month.MARCH, 1);
LocalDate endLocatDate = LocalDate.of(2015, Month.OCTOBER, 1);

Period period = Period.between(startLocatDate, endLocatDate);
System.out.println(period.getMonths()); // 7달

LocalDate next = endLocatDate.plus(period);
System.out.println(next); // 7달 뒤

}

@Test
public void timeStampTest() {
System.out.println();
Instant timestamp = Instant.now();
System.out.println(timestamp);
}

@Test
public void formatterTest() {
System.out.println();
String day = "20150901";
LocalDate localDate = LocalDate.parse(day, DateTimeFormatter.BASIC_ISO_DATE);
System.out.println("day : " + localDate);

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM uuuu").withLocale(Locale.ENGLISH);
String anotherDate = "04 Aug 2015";
LocalDate parsedLocalData = LocalDate.parse(anotherDate, dateTimeFormatter);
System.out.println(anotherDate + " parses to " + parsedLocalData);
}

}


결과


day : 2015-09-01

04 Aug 2015 parses to 2015-08-04


Clock : SystemClock[Z]

Clock (zone) : Z

LA Clock : SystemClock[America/Los_Angeles]


2015-05-19T15:34:55.525Z


2015-05-20

2015.5.20

2015-12-25

same day : 2015-12-25

yearMonth : 2015-05

monthday : --12-25

Today is not birthday

true

1 week after : 2015-05-27

1 day after : 2015-05-21

1 century after : 2115-05-20

1 year after : 2016-05-20

leap year : false


7

2016-05-01


time : 00:34:55.530

2 hours after : 02:34:55.530

3 hours before : 22:34:55.530


Process finished with exit code 0




새로 추가된 Java8 Date와 Time에 좋은 자료는 아래에 있다. 아주 디테일하게 정리된 자료이다. 

http://www.ne.jp/asahi/hishidama/home/tech/java/datetime.html



Posted by '김용환'
,



아래 Java8의 LocalDate.parse()를 그냥 예제대로 사용하면, ParseException이 발생한다. Java8의 초창기 버전에서는 아래 코드를 문제없이 지원했으나, 최근 버전에서는 세밀해졌다. 

@Test
public void formatterTest() {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM uuuu");
String anotherDate = "04 Aug 2015";
LocalDate parsedLocalData = LocalDate.parse(anotherDate, dateTimeFormatter);// 에러 발생
System.out.println(anotherDate + " parses to " + parsedLocalData);
}

Exception

java.time.format.DateTimeParseException: Text '04 Aug 2015' could not be parsed at index 3

at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947)

at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849)

at java.time.LocalDate.parse(LocalDate.java:400)




해결을 위해서는 Pattern에서 Local 정보를 추가해야 Exception이 발생하지 않는다. 

@Test
public void formatterTest() {

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd MMM uuuu").withLocale(Locale.ENGLISH);
String anotherDate = "04 Aug 2015";
LocalDate parsedLocalData = LocalDate.parse(anotherDate, dateTimeFormatter);
System.out.println(anotherDate + " parses to " + parsedLocalData);
}

결과 

04 Aug 2015 parses to 2015-08-04


Posted by '김용환'
,


java7 & play 1.2.x 에서 java8 & play 1.3.0으로 migration 한 후기를 작성한다.



play 1.2.x를 java8로 실행하면 에러가 발생. 그래서 play1 의 java8 패치를 기다렸다.


하지만, java8 support가 revert 되었던 적이 있었지만..

https://github.com/playframework/play1/commit/ea7a14ae432d24ac3f73c5de1c70d9037db8c5c0



최근에 java8 support가 지원되었다. 

https://github.com/playframework/play1/commit/9778f24dda5c22b7df9b1cc6fd01cd492799d377




내용을 보면 jdt core의 버전(3.7->3.9)과 ApplicationCompiler클래스의 java8 지원 코드이다. CompilerOption은 eclipse jdt의  org.eclipse.jdt.internal.compiler.impl.CompilerOptions 이다. 1.8이 추가된 것이었다.


framework/src/play/classloading/ApplicationCompiler.java

+        }else if("1.8".equals(Play.configuration.get("java.source"))) {

+            javaVersion = CompilerOptions.VERSION_1_8;

         }



이 코드에 필받아 기존에 동작중이었던 java7 & play1.2.x 에서 점프했다. 

 java8 & play1.3.0이 무사하게 동작되고 있다.



* 참고 

jdt를 이용한 java8 컴파일 예제.

https://blogs.nologin.es/rickyepoderi/uploads/CompilingServletpartI/SimpleCompiler.java






Posted by '김용환'
,


Collections.EMPTY_LIST는 사용할 때 주의를 해야 한다. 빈 껍데기 리스트를 생성하면서 add()는 호출하면 exception이 나는 구조이다. 


@Test
public void test() {
// collections empty list
List<String> list = Collections.EMPTY_LIST;

try {
list.add("10");
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}

//guava empty list
List<String> myList = Lists.newArrayList();
try {
myList.add("10");
System.out.println("no exception in guava list");
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}


guava의 Lists.newArrayList()는 ArrayList 구현체를 전달하는 반면, 

Collections.EMPTY_LIST를 구현체가 있지만 add() 메소드를 구현하지 않았다. 

따라서 위의 테스트 코드는 아래 에러가 발생한다.


java.lang.UnsupportedOperationException : null

at java.util.AbstractList.add(AbstractList.java:148)

at java.util.AbstractList.add(AbstractList.java:108)



public class Collections { ... public static final List EMPTY_LIST = new EmptyList<>();

..
 */
private static class EmptyList<E>
extends AbstractList<E>
implements RandomAccess, Serializable {
private static final long serialVersionUID = 8842843931221139166L;

public Iterator<E> iterator() {
return emptyIterator();
}
public ListIterator<E> listIterator() {
return emptyListIterator();
}

public int size() {return 0;}
public boolean isEmpty() {return true;}

public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }

public Object[] toArray() { return new Object[0]; }

public <T> T[] toArray(T[] a) {
if (a.length > 0)
a[0] = null;
return a;
}

public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}

public boolean equals(Object o) {
return (o instanceof List) && ((List<?>)o).isEmpty();
}

public int hashCode() { return 1; }

@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
return false;
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
}
@Override
public void sort(Comparator<? super E> c) {
}

// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
}

@Override
public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }

// Preserves singleton property
private Object readResolve() {
return EMPTY_LIST;
}
}



따라서 모든 List는 add() operation을 구현하고 있다는 것을 가정할 수 없다. List 생성할 때는 항상 신중해야 겠다..




참고로..Collections.emptyList()도 동일하게 에러가 발생한다. 


List list = Collections.emptyList();
list.add("11");


그 이유는 해당 메소드는 EMPTY_LIST를 그대로 리턴하기 때문이다. 

public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}



Posted by '김용환'
,



Sorting을 이용한 Java 8 lamda / (새로 추가된) javax.util.Comparator api 테스트 


java7은 comparator와 guava ordering을 통해서 sorting을 할 수 있다.


https://gist.github.com/knight1128/fbb711b1dd8eea38dd60

package com.google.locationlab;

import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;

import com.google.common.primitives.Ints;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.junit.Before;
import org.junit.Test;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Java8Test {
    private static List<Person> persons;

    @Before
    public void before() {
        persons = Lists.newArrayList();
        persons.add(new Person(1, "Samuel", 30));
        persons.add(new Person(2, "Jason", 25));
        persons.add(new Person(3, "Brian", 55));
        persons.add(new Person(4, "Cato", 32));
        //System.out.println(persons);
    }

    // java.util.Collection sorting
    @Test
    public void java7CollectionSortTest() {
        Collections.sort(persons, new Comparator<Person>() {
            public int compare(Person p1, Person p2) {
                return p1.age.compareTo(p2.age);
            }
        });
        System.out.println("java7CollectionSortTest : " + persons);
    }

    @Test
    public void java7GuavaCollectionSortTest() {

        Collections.sort(persons, new Ordering<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return Ints.compare(p1.age, p2.age);
            }
        });
        System.out.println("java7GuavaCollectionSortTest : " + persons);
    }

    @Test
    public void java8LamdaWithTypeCollectionSortTest() {
        Collections.sort(persons, (Person p1, Person p2) -> Ints.compare(p1.age, p2.age));
        System.out.println("java8LamdaWithTypeCollectionSortTest : " + persons);
    }

    @Test
    public void java8LamdaWithoutTypeCollectionSortTest() {
        Collections.sort(persons, (p1, p2) -> Ints.compare(p1.age, p2.age));
        System.out.println("java8LamdaWithoutTypeCollectionSortTest : " + persons);
    }

    @Test
    public void java8LamdaSortTest() {
        persons.sort((p1, p2) -> p1.age.compareTo(p2.age));
        System.out.println("java8LamdaSort : " + persons);
    }

    @Test
    public void java8ComparatorSortTest() {
        persons.sort(Comparator.comparing(Person::getAge));
        System.out.println("java8LamdaSort : " + persons);
    }

}

class Person {
    Integer id;
    String name;
    Integer age;

    public Person(int id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}





결과

java8LamdaWithoutTypeCollectionSortTest : [Person[id=2,name=Jason,age=25], Person[id=1,name=Samuel,age=30], Person[id=4,name=Cato,age=32], Person[id=3,name=Brian,age=55]]

java8LamdaWithTypeCollectionSortTest : [Person[id=2,name=Jason,age=25], Person[id=1,name=Samuel,age=30], Person[id=4,name=Cato,age=32], Person[id=3,name=Brian,age=55]]

java7CollectionSortTest : [Person[id=2,name=Jason,age=25], Person[id=1,name=Samuel,age=30], Person[id=4,name=Cato,age=32], Person[id=3,name=Brian,age=55]]

java8LamdaSort : [Person[id=2,name=Jason,age=25], Person[id=1,name=Samuel,age=30], Person[id=4,name=Cato,age=32], Person[id=3,name=Brian,age=55]]

java7GuavaCollectionSortTest : [Person[id=2,name=Jason,age=25], Person[id=1,name=Samuel,age=30], Person[id=4,name=Cato,age=32], Person[id=3,name=Brian,age=55]]



* 참고

Comparator 클래스의 comparing 메소드의 내부는 Lamda로 구현되어 있다.

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor)
{
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));

}


Posted by '김용환'
,


Java7의 Guava의 FluentIterable 과 Java8의 Guava의 FluentIterable 를 비교해서 코딩했다. 




import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static org.junit.Assert.assertEquals;

public class GuavaTest {

List<Person> persons = Lists.newArrayList();

@Before
public void before() {
Person samuel = new Person(10, "Samuel");
Person jason = new Person(25, "Jason");
Person kelly = new Person(21, "Kelly");

persons.add(samuel);
persons.add(jason);
persons.add(kelly);
}

@Test
public void simpleGuavaWithJava7() {
List<String> names = FluentIterable.from(persons)
.filter(new Predicate<Person>() {
@Override
public boolean apply(Person person) {
return person.age() >= 20;
}
})
.transform(new Function<Person, String>() {
@Override
public String apply(Person person) {
return person.name();
}
})
.toList();

assertEquals("Jason", names.get(0));
assertEquals("Kelly", names.get(1));
assertEquals(2, names.size());
}

@Test
public void simpleGuavaWithJava8() {
List<String> names = FluentIterable.from(persons)
.filter(person -> person.age() >= 20)
.transform(person -> person.name())
.toList();

assertEquals("Jason", names.get(0));
assertEquals("Kelly", names.get(1));
assertEquals(2, names.size());
}
}

class Person {
int age;
String name;

public Person(int age, String name) {
this.age = age;
this.name = name;
}

public int age() {
return age;
}

public String name() {
return name;
}

}




Posted by '김용환'
,

 java 8 migration하면서 좋은 팁을 소개한다. 


java 7에서 java8로 migration할 때는 Oralce의 java se 8 compatibility guide 링크를 참고한다. 

http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html



The class file version for Java SE 8 is 52.0 as per the JVM Specification. Version 52.0 class files produced by a Java SE 8 compiler cannot be used in earlier releases of Java SE.


삭제된 것은 install과 deploy 관련된 부분들이 존재한다. 

http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html#A999476


deprecated된 것들

http://www.oracle.com/technetwork/java/javase/8-compatibility-guide-2156366.html#A1000033



GC 관련해서 바뀐 부분이 존재한다.

class 를 저장하던 metadata 영역이 head에서 native memory로 넘어간다. 



Area: HotSpot / gc 

Synopsis

The command line flags PermSize and MaxPermSize have been removed and are ignored. If used on the command line a warning will be emitted for each.

Java HotSpot(TM) Server VM warning: ignoring option PermSize=32m; support 
was removed in 8.0
Java HotSpot(TM) Server VM warning: ignoring option MaxPermSize=128m; support 
was removed in 8.0
Nature of Incompatibility

source




Area: HotSpot / gc 

Deprecated Feature

The following garbage collector combinations are deprecated:

  • DefNew + CMS

  • ParNew + SerialOld

  • Incremental CMS

Corresponding command-line options produce warning messages and it is recommended to avoid using them. These options will be removed in one of the next major releases.

  • The -Xincgc option is deprecated

  • The -XX:CMSIncrementalMode option is deprecated. Note that this also affects allCMSIncremental options.

  • The -XX:+UseParNewGC option is deprecated, unless you also specify -XX:+UseConcMarkSweepGC.

  • The -XX:-UseParNewGC option is deprecated only in combination with -XX:+UseConcMarkSweepGC.





*  permsize 

MaxPermSize 매개변수와 permSize 매개변수는 더 이상 java8에서 사용하지 않는다. 

이 영역은 java7 이전에는 permanent 영역에 있었지만, java8 부터는 metaspace영역(native heap)으로 이동하게 되었다. 


이 영역에 대한 제어를 하려면, –XX:MaxMetaspaceSize (기본 값은 21MB)를 사용해야 할 필요가 있다. 관련된 매개변수로  ‑XX:MinMetaspaceFreeRatio와 ‑XX:MaxMetaspaceFreeRatio 가 존재한다..


https://www.infoq.com/articles/Java-PERMGEN-Removed

Posted by '김용환'
,