2016의 게시물 표시

JMX Remote 설정 후 Heap dump 추출하기

이미지
Java Mission Control 로 Heap dump 추출하는 방법 1. JVM Browser 탭 에서 Heap dump를 추출하고자 하는 대상 선택 2. MBean Server 클릭 3. MBean Browser 탭 클릭 (우측 하단 두번째 탭) 4. MBean Tree 에서 보이는 폴더명 중 com.sun.management 클릭 5. HotSpotDiagnostic 항목 클릭 6. MBean Tree 우측 창에 MBean Features 에서 Operations 탭 클릭 7. dumpHeap : void 항목 클릭 8. p0와 p1 항목의 value 에 각각  dump 파일명 과  true  값을 지정 9. 하단의 Execute 버튼 클릭하여 dump 파일 생성 및 확인 10. dump 파일은 프로세스의 현재 작업중인 폴더에서 찾을 수 있다.  만약 ps 명령어를 통해 알아낸 pid가 4455라면 pwdx 4455 명령어를 통해  현재 작업중인 폴더를 알아낼 수 있다. 동일한 파일명이 존재할 경우 아래와 같은 에러 발생한다.  파일명 변경 후 execute 하여 생성하면 된다.  refs:  heap dump 추출방법

JMX Remote 설정

이미지
1. 기본 tomcat 에는 JMC 연결을 위한 모듈이 없기 떄문에 catalina-jmx-remote.jar 파일을 다운로드 한다.  나는 Tomcat 8 을 사용하고 있어 아래 링크에서 다운로드 받았다.  자신의 Tomcat 버전에 맞는 파일로 받아서 다운로드 받을것을 권장한다.  주의) Tomcat 8.0.28 버전을 사용하고 있을 때 Tomcat 8 버전의  catalina-jmx-remote.jar 다운로드 받아 실행하였더니  파싱에러가 발생하였다. Tomcat 7 버전의 파일로 다시 받아 실행하였더니 정상적으로 작동하였다.  Tomcat 7과 Tomcat 8 의 catalina-jmx-remote.jar 은 해시값이 다른 즉 동일한 파일이 아니었기 때문에 8.0.28 버전에 일부 반영이 되지 않은 부분이 있었다는 생각이 든다. Tomcat8버전의 jmx파일 다운로드 링크 2. server.xml 에 jmx 리스너 등록 3. jmx 환경설정을 위한 쉘 스크립트 생성 후 실행 (실행권한 줄 것) 4. jmc.exe 파일을 클릭하여 실행 5. 왼쪽 상단의 File > Connect.. 를 클릭하여 신규 연결생성 6. 연결할 서버의 주소와 포트정보 입력 7. 테스트 연결 확인   ( status 가 ok가 아니라면 jmx 리스너 또는 방화벽  확인할 것 ) 8. JMX 콘솔 실행 9. 완료 화면 refs:  https://www.lesstif.com/pages/viewpage.action?pageId=20776824

[MySQL] datetime 의 default value 설정하기

ALTER TABLE "테이블명" MODIFY COLUMN create_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;

[Tomcat] java.lang.NoClassDefFoundError: org/springframework/security/taglibs/authz/AuthorizeTag

 서비스가 정상적으로 올라오지 않아 톰캣로그를 확인하던중 아래와 같은 에러를 확인했다. java.lang.NoClassDefFoundError: org/springframework/security/taglibs/authz/AuthorizeTag  톰캣이 오래된 security.tld (태그 라이브러리) 를 캐시하고 있어서 발생하는 문제이다. 해결방법은 톰캣 홈경로에 위치해 있는 work 디렉토리를 지워주고 재시작을 하면 된다.  나의 경우 /usr/local/apache-tomcat/work 에 위치해 있었으며 해당 폴더를 삭제하여 정상작동 하였다. refs : http://stackoverflow.com/questions/7678421/spring-security-3-1-java-lang-classnotfoundexception-org-springframework-securi

[JAVA] String.lengh() VS String.getBytes().length

http://www.pixelstech.net/article/1427944920-String-length()-vs-String-getBytes()-length-in-Java UI 에 response 타입에 content-length 를 String.lengh()로 보냄 길이가 다름. (원래 길이보다 모자르게 감) String.getBytes().length로 해야 일치.

[MySQL] Error Dropping Database (Can't rmdir '.test\', errno: 17)

InnoDB가 깨져서 복구가 불가능해 졌다. 덤프 데이터가 있어서 Database 를 drop 후 다시 생성하려 했지만 아래와 같은 에러가 발생하면서 drop이 되지 않았다.  Error Dropping Database (Can't rmdir '.데이터베이스명\', errno: 17) 위의 에러는 MySQL에서 data 디렉토리에 위치한 Database 관련 디렉토리를 삭제하지 못해서 발생한다. 이러한 경우에는 MySQL에서 Database를 저장하는 디렉토리에 가서 직접삭제를 해주어야 한다. 예를 들어 DB가 설치된 경로가 /usr/local/mysql 이고, drop 하고자 하는 Database가 test 라면 아래와 같이 진행한다. cd /usr/loacl/mysql/data   (Database 가 저장 된 폴더) rm -rf test (test Database 폴더 삭제) mysql 에 접속 create database test; (Database 다시 생성) refs : http://stackoverflow.com/questions/4584458/error-dropping-database-cant-rmdir-test-errno-17

[MySQL] 외부에서 IP로 MySQL로 연결 시 Connection 이 느려지는 현상 해결

 운영하고 있던 서버중 하나에서 DB 연결을 하는데 6초 가량 걸리는 일이 발행하였다. 이전에는 문제가 없었기에 살펴보던 중 MySQL에서 IP로 접속 시 DNS lookup 즉, IP 와 hostname 이 일치하는가를 확인하는 과정에서 연결이 지연될 수 있음을 확인하였다. /etc/my.cnf 파일에 [mysqld] 항목 아래에 --skip-name-resolve 옵션을 추가하여 해결. 주의 : --skip-name-resolve 옵션을 사용한다면, 호스트명 대신 IP로만 접속을 할 수 있다. refs : http://dev.mysql.com/doc/refman/5.7/en/host-cache.html http://dev.mysql.com/doc/refman/5.7/en/server-options.html#option_mysqld_skip-name-resolve

[JAVA8] 중복제거 하기

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; public class Distinct { public static void main(String[] args) { System.out.println("defaultDistinctWithOnlyString"); List names = Arrays.asList("aaa", "bbb", "ccc", "ddd", "aaa", "ccc", "aaa", "aaa"); List distinctList = names.stream().distinct().collect(Collectors.toList()); distinctList.forEach(System.out::println); // result : aaa , bbb, ccc , ddd // 다음의 경우에는 기대와는 다른 결과가 나올 수 있다. Person p1 = new Person(); Person p2 = new Person(); Person p3 = new Person(); Person p4 = new Person(); Person p5 = new Person(); p1.setName("aaa"); p1.setAge(20); p1.setHeight(175); p2.setName("bbb"); p2.

[JAVA8] 람다식을 이용하여 Sorting 하기

public class SortVO { // 숫자 비교를 하기위해 int 가 아닌 Integer로 선언 Integer no; String name; public Integer getNo(){ return no; } public void setNo( Integer no ){ this.no = no; } public String getName(){ return name; } public void setName( String name ){ this.name = name; } } public class LambdaSortingTest { public static void main( String[] args ){ SortVO st1 = new SortVO(); SortVO st2 = new SortVO(); SortVO st3 = new SortVO(); SortVO st4 = new SortVO(); SortVO st5 = new SortVO(); SortVO st6 = new SortVO(); st1.setNo(111); st2.setNo(212); st3.setNo(3232); st4.setNo(443); st5.setNo(5); st6.setNo(622); List list = new ArrayList<>(); list.add(st1); list.add(st2); list.add(st3); list.add(st4); list.add(st5); list.add(st6); System.out.println("<< Integer List >>"); list = list.stream().sorted(( e1, e2 ) -> e1.getNo().compareTo(e2.getNo())).collect(Collectors.toList());

[Tomcat] SE[VERE: IOException while loading persisted sessions: java.io.EOFException

이미지
젠킨스를 이용하여 자동빌드를 하던 도중 갑자기 connection refuse 에러가 발생. 카탈리나 로그를 확인해 보니 아래와 같은 에러가 발생하며 배포가 되지 않았다. SEVERE: IOException while loading persisted sessions: java.io.EOFException Tomcat 디렉토리를 clean 해주지 못하는 경우 발생. 문제가 발생한 app 경로를 찾아가 SESSION.ser 파일을 삭제해주면 깔끔하게 해결된다. ${catalina.home}/work/Catalina/localhost/<app>/SESSION.ser    나의 경우는  ${catalina.home}/work/Catalina/localhost/manager에 있는 SESSION.ser 파일을  삭제해 주어 해결하였다.  refs :  http://stackoverflow.com/questions/12348170/what-is-wrong-with-my-config-severe-ioexception-while-loading-persisted-sessio

[JAVA8] 람다식을 이용한 Batch Insert 구현하기

Java 8 에서 람다식을 이용한 Batch Insert 구현하기   조회한 데이터의 사이즈가 커서 일정 단위로 잘라 넣어야 할 일이 생겼다. 람다식을 이용한 메서드를 만들어 사용하였으며, 간결하다고 생각되어 해당 메서드를  공유해 본다. public static <T>Stream <List<T>>   batches (List<T> source, int length) {   if (length <= 0) throw new IllegalArgumentException("length = " + length);   int size = source.size();   if (size <= 0) return Stream.empty();   int fullChunks = (size - 1) / length;   return IntStream.range(0, fullChunks + 1).mapToObj(           n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length)); }  (코드 스타일이 적용이 되지 않아 실제 구현된 메서드는 텍스트로 표현) // 사용 예) public static void main(String[] args) { List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); System.out.println("By 3:"); batches(list, 3).forEach(System.out::println); System.out.println("By 4:"); batches(list, 4).forEach(System.out::println); } refs :  http://stackoverflow.com/q

[JAVA8] HashMap에 getOrDefault 와 putIfAbsent 의 차이

getOrDefault : key 값이 없다면 입력시 설정한 default 값을 반환 putIfAbsent : key 값이 없다면 입력 된 key와 value 를 입력, 해당 key가 존재하면 입력 되었던 값 반환 HashMap hm = new HashMap<>(); // 1. 비어있는 HashMap에서 get 호출 System.out.println("key가 없을 때 : " + hm.get("key")); // 결과 : key가 없을 때 : null // 2. 비어있는 HashMap에서 getOrDefault 호출 System.out.println("getOrDefault() : " + hm.getOrDefault("key", "car")); // 결과 : getOrDefault : car // 3. key, value 입력 System.out.println("putIfAbsent() : " + hm.putIfAbsent("key", "ship")); // 결과 : putIfAbsent : null // 이전값이 존재하지 않기 때문에 null 반환 // 4. putIfAbsent으로 key, value 입력 후 동일한 key 값 재호출 System.out.println("putIfAbsent() : " + hm.putIfAbsent("key", "bike")); // 결과 : putIfAbsent : ship System.out.println("values in map : "+hm.toString()); // 결과 : {key=ship} // getOrDefault은 해당 key가 없을 경우 값을 set은 하지 않고 정해진 default 값만 리턴 하기 떄문에 car 없음 // putIfAb

[HTTPS] Hostname in cerificate didn't match?

특정 업체의 API를 호출하던 중 아래와 같은 에러가 발생 Hostname in certificate didn't match? SSLPeerUnverifiedException   위의 에러발생 이유는 해당 업체의 인증서가 나에게 등록 되어있지 않기 때문이다. 해당 업체의 인증서를 등록하여 해결하는 방법도 있지만, 나는 데이터가 원하는데로 전달되는지만 확인하면 되었기에 인증서를 무시하고 요청하는 방식을 사용하였다. pom.xml 에 httpclient 추가 <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId> httpclient </artifactId> <version>4.5.1</version> <type>jar</type> <scope>compile</scope> </dependency> 인증서 무시를 위해 사용한 코드 @Test public void shouldAcceptUnsafeCerts() throws Exception{ HttpClient httpclient = httpClientTrustingAllSSLCerts(); final String uri = "YOUR URI"; HttpGet httpGet = new HttpGet(uri); HttpResponse response = httpclient.execute(httpGet); System.out.println(EntityUtils.toString(response.getEntity())); } private HttpClient httpClientTrustingAllSSLCerts() throws HttpClientBuilder builder = HttpClie

[Android] Android 로깅 시 isLoggable() 메서드 사용

아래와 같이 isLoggable 이라는 메서드를 사용하여 원하는 로그를 찍고 싶을 경우 system property 값을 원하는 로그 레벨로 변경해 주거나 local.prop 파일을 생성하여 /data/local.prop 으로 위치시켜야 한다. public static void LOGD(final String tag, String message, Throwable cause) {         if (LOGGING_ENABLED){             if (Log. isLoggable (tag, Log.DEBUG)) {                 Log.d(tag, message, cause);             }         }   } system property 값을 변경해 주는 방법은 다음과 같다. adb shell setprop log.tag.<tag> <log level> myLog 라는 tag 를 debug 레벨에서 찍고 싶다면, console 창에서 아래와 같이 써주면 된다. adb shell setprop lgo.tag. myLog DEBUG * 공식사이트에 나와있는 isLoggable 메서드 관련 설명 public static boolean  isLoggable   ( String  tag, int level) Added in  API level 1 Checks to see whether or not a log for the specified tag is loggable at the specified level. The default level of any tag is set to INFO. This means that any level above and including INFO will be logged. Before you make any calls to a logging method you should check to see if your tag

[Spring] @PropertySource and Environment 사용시 Property 값이 null 로 들어오는 경우

Spring에서 Property 값을 아래와 같이 가져올 수 있다. @Configuration @PropertySource("classpath:myProperties.properties") public class MyConfiguration { @Autowired Environment environment; public DataSource getDataSource(){     dataSource.setDriverClassName(environment.get("jdbc.driverClassName"));     return dataSource; } } 하지만, Autowiring이 늦게 발생하는 경우 environment 에는 값이 없는 상태로 MyConfiguration 의 getDataSource() 메서드가 먼저 실행된다. 일종의 트릭이지만, org.springframwork.context.EnvironmentAware 를 implement 하여 해결할 수 있다. @Configuration @PropertySource("classpath:myProperties.properties") public class MyConfiguration implements EnvironmentAware {  private Environment environment;  @Override  public void setEnvironment(final Environment environment) {   this.environment = environment;  }  public void myMethod() {   final String myPropertyValue = environment.getProperty("myProperty");   // ...   } } refs : http://stackoverflow.com/questions

[SVN] commit fails with “Authorization failed” error

SVN 저장소를 새로 만들어서 소스코드를 업로드하는 중에 다음과 같은 에러가 발생하였다. SVN commit fails with “Authorization failed” error SVN 생성 폴더의 conf/svnserve 에 있는 디렉토리 접근 권한을 설정해 주지 않아서 발생한 문제였다. auth-access = write 설정을 추가하여 해결 하였다.

[Android] Android Local Unit Tests 환경 구성

이미지
Android 앱 개발 시 테스트하는 방법은 두가지가 있다. Instrumented Unit Tests Local Unit Tests 그중 하나인 Local Unit Tests 환경설정을 정리해 본다.  Local Unit Test 는 테스트하고자 하는 코드가 Android System 에 크게 의존적이지 않을 때 사용한다. 환경설정 폴더 생성 : 테스트 코드는 src/test/java 폴더에 위치해야 한다. 프로젝트 구조 build.gradle - dependancies 추가 testCompile  'junit:junit:4.12' testCompile  'org.mockito:mockito-core:1.10.19' testCompile  'org.hamcrest:hamcrest-library:1.1' 테스트 코드 작성 테스트 코드 구조 테스트 실행  안드로디으 스튜디오에 있는  Build Variants 창 클릭  Test Artifact 를 Unit Tests 로 변경   Run 메뉴에서 Unit Test 를 실행 Unit Tests 가 활성화 된 화면 ref : http://developer.android.com/intl/ko/training/testing/unit-testing/local-unit-tests.html