반응형

1. 로그 레벨 출력이 불가하다.

  • 로깅 프레임워크처럼 개발환경에 따른 로그 레벨을 설정할 수 없다.(Logback의 로그레벨 : TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
  • 그렇기 떄문에 각 환경마다 로그 설정이 불가하다.
  • 예를 들면, 프로덕션 환경에서 디버그 레벨의 로그를 제거하고 싶은 경우 코드를 통해 일일히 제거해야한다.
      

2. 로그에 필요한 최소한의 정보가 없다.

  •  System.out.println은 단순히 문자열을 찍는 메서드여서, 로깅시 필요한 날짜, 시각, 문제의 수준, 위치 등의 정보를 따로 표시할 수 없다.

 

3. 휘발성

  • System.out.println은 표준 출력으로만 사용되고, 따로 기록되지 않는다. 로그 파일로서 관리가 불가하여 사후 처리시, 로그를 확인할 수 없다.

 

3. 성능저하

  •  단순 디버깅 용도여도 System.out.println을 사용하지 않는 이유는 성능 저하 때문이다.
  • println은 synchronized로 동기화 처리가 되어있어, 오버헤드가 발생할 수 있다.
  • synchronized는 메서드나 블록 코드에 동기화 영역을 표시하는 것으로, 동기화된 불록은 한 시점에 1개의 스레드만 접근이 가능
  • System.out.println() 메서드를 여러 스레드가 사용하게 된다면 오버헤드가 발생하여 프로세스 처리가 늦어지게 될 수 있다. (* 오버헤드(Overhead) : 어떤 처리를 하기 위해 추가로 들어가는 처리 시간, 메모리 등의 컴퓨터 자원을 말합니다.)
  • Blocking I/O
      

cf. 코딩 테스트시에 System.out.println을 사용하여 출력하면 시간초과가 발생할 수 있다.

 

15649번: N과 M (1)

한 줄에 하나씩 문제의 조건을 만족하는 수열을 출력한다. 중복되는 수열을 여러 번 출력하면 안되며, 각 수열은 공백으로 구분해서 출력해야 한다. 수열은 사전 순으로 증가하는 순서로 출력해

www.acmicpc.net

References

 

 

로깅을 System.out.println() 로 하면 안되는 이유

학습 배경 우테코 레벨3 팀프로젝트 3차 데모데이 요구사항 중 하나는 ‘디버깅할 수 있는 로그 파일 출력’ 이다. 이전까지는 로깅에 대해 전혀 신경쓰지 않고 있었는데, 슬슬 로깅에도 신경써

hudi.blog

 

'개발 > Java' 카테고리의 다른 글

String, StringBuilder, StringBuffer  (0) 2022.12.13
[Java] Garbage Collection(가비지 컬렉션)  (2) 2022.12.02
equals()  (0) 2022.11.30
[자바/JAVA] 정적 변수와 메서드 (static)  (0) 2021.06.25
[자바/JAVA] this  (0) 2021.06.24
반응형

1. String, StringBuilder, StringBuffer
 - String은 상수이며, 값을 만든 뒤 변경할 수 없다 (Immutable)
 - String 클래스의 한계 (불변객체 > immutable)
  > immutable(불변)한 특성으로 인해 문자열 변경시 메모리 낭비가 발생 (이전 문자열은 GC에 의해 제거) 
  > 문자열을 변경할 때마다 새로운 메모리가 할당됨
 - StringBuffer와 StringBuilder는 String과는 다르게 변형 가능(mutable)하고, 내부적으로 배열의 형태로 
   선언되기 때문에 문자열 처리 후 새로운 인스턴스가 할당되는 것이 아닌 기존의 객체에 이어 붙인다. 
   따라서 훨씬 속도도 빠르고 공간의 낭비도 적다.

2. StringBuilder
 - 문자열을 변경하거나 이어붙이는 경우 추가 메모리 생성없이 기존 문자열이 변경되는 클래스 (가변객체 > mutable)
 - 멀티 쓰레드 환경에서 문자열의 안전한 변경을 보장해주지 않는다. (여러 쓰레드가 동시에 접근/변경하는 경우 수행결과가 올바르지 않음)

3. StringBuffer
 - StringBuilder와 마찬가지로 문자열을 이어붙이는 경우 추가 메모리 생성없이 기존 문자열이 확장되는 클래스 (가변객체 > mutable)
 - StringBuffer는 멀티쓰레드 환경에서 문자열의 안전한 변경을 보장한다. (두 쓰레드가 동시에 문자열에 접근하더라도 안전한 변경을 보장)

4. StringBuilder와 StringBuffer의 차이
 - 동기화 : StringBuffer는 동기화 기능 지원, StringBuilder는 동기화 미지원이지만 단일 쓰레드에서는 StringBuffer보다 빠르다.
 - 언제 어느걸 써야할까?
  > StringBuilder : 싱글 쓰레드 환경에 적합, 스레드가 안전한 프로그램이거나 오류가 나도 큰 이슈가 없고 성능이 중요한 경우
    > StrngBuffer : 멀티 쓰레드 환경에 적합, 연산이 많을 경우 유리

5. 성능 차이 (String vs StringBuilder vs StringBuffer)
 - 3개의 성능을 비교해보면 StringBuilder > StringBuffer > String 순으로 StringBuilder가 제일 빠름
 - 싱글 쓰레드인 경우 StringBuilder와 StringBuffer의 성능 차이 > StringBuilder가 연산속도가 빠르다
 
* 참고
 - https://life-with-coding.tistory.com/485
 - https://blog.neonkid.xyz/286

'개발 > Java' 카테고리의 다른 글

System.out.println() 사용 안하는 이유  (0) 2022.12.14
[Java] Garbage Collection(가비지 컬렉션)  (2) 2022.12.02
equals()  (0) 2022.11.30
[자바/JAVA] 정적 변수와 메서드 (static)  (0) 2021.06.25
[자바/JAVA] this  (0) 2021.06.24
반응형

1. GC 란?

  • JVM의 Heap 영역에서 사용하지 않는 객체의 메모리를 자동으로 수거하는 기능

 

2. GC의 수거대상

  • Heap 영역에는 Object 타입의 데이터(String, List 등)들이 들어가는데, GC Roots에 UnReachable한 Object가 대상
  • 어떤 객체의 참조가 존재한다면 Reachable, 그렇지 않다면 UnReachable이라고 한다.
  • GC Root에서 시작해 이 Root가 참조하는 모든 오브젝트, 또 그 오브젝트들이 참조하는 다른 오브젝트들을 탐색해 내려가며 마크(Mark)한다.이 탐색해 내려가며 마크하는 것을 Mark단계라고 한다. (Reachable 한 Object)
  • 마크(Mark)되지 않은 객체 (UnReachable한 Object)
  • GC Roots 란?  GC Root들은 힙 외부에서 접근할 수 있는 변수나 오브젝트
    • 실행중인 쓰레드 (Active Thread) 
    • 정적 변수 (Static Variable) 
    • 로컬 변수 (Local Variable) 
    • JNI 레퍼런스 (JNI Reference)

3. GC의 동작순서 (Mark &Sweep)

  • Mark > GC Roots로부터 모든 변수를 스캔하면서 각각 어떤 객체를 참조하는지 찾아서 마킹하는 작업
  • Sweep > 마킹되지 않은 UnReachable한 객체들을 Heap에서 제거하는 작업
  • Compact > Sweep 후에 분산된 객체들을 Heap의 시작주소로 모아 메모리가 할당된 부분, 그렇지 않은 부분으로 나눈다. (메모리 단편화 방지)

 

4. Heap 영역 구조

  • Young Generation (새로운 객체들이 할당되는 영역)
    • Eden
    • Survivor0
    • Survivor1
  • Old Generation (Young Generation에서 오랫동안 살아남은 객체들이 존재하는 영역)
  • meta space (가비지 컬렉션 시에 필요한 클래스와 메소드의 요약 정보가 존재하는 영역)

 

5. GC 동작 과정

  1. 새로운 객체들이 Eden 영역에 할당
  2. Eden 영역이 꽉 찬다
  3. Minor GC 발생 (Mark&Sweep)
    1. Mark > Reachable 한 객체들을 마킹
    2. Reachable 한 객체들은 Survivor 영역으로 이동  (Survivor0 또는 Survivor1 > 한 곳으로만 이동 가능)
    3. UnReachable 한 객체들은 Sweep 처리
    4. Survivor 영역에 있는 살아남은 객체들의 age가 증가한다. (Aging)
  4. 다시 Eden 영역이 꽉 차고, Minor GC가 발생 반복 (1~3번)
  5. 객체 age가 임계점에 도달하면 Old Generation으로 이동한다 (Promotion)
  6. Old Generation이 꽉 차면 Major GC가 일어난다.

 

6. GC 특징

1. stop - the-world

  • GC를 실행하기 위해 jvm이 애플리케이션 실행을 멈추는 것
  • GC를 실행하는 쓰레드 외의 모든 쓰레드가 작업을 중단한다.

2. Minor GC와 Major GC로 나뉘어져 있는 이유 (성능 최적화)

  • 대부분의 객체는 금방 접근 불가능한 상태(unreachable)가 된다. 즉, 금방 garbage가 된다.
  • 오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다.
  • 보통 Minor GC에서 객체들이 수거됨. 빈번하게 발생해도 괜찮도록 구성 (Eden, Survivor)
  • Major GC에서 수거되는 객체들은 미비함.

7. GC의 종류

  • Serial GC
    • GC를 처리하는 쓰레드가 1개
    • 다른 GC에 비해 stop-the-world 시간이 길다.
    • Mark-Complete(Sweep포함) 알고리즘 사용
  • Parallel GC
    • Java8의 default GC.
    • Young 영역의 GC를 멀티 쓰레드로 수행
    • Serial GC에 비해 stop-the-world 시간 감소
  • Parallel GC
    • Parallel GC를 개선
    • Old 영역에서도 멀티 쓰레드 방시의 GC 수행
    • Mark-Summary-Compact 알고리즘 사용
  • CMS GC (Concurrent Mark Sweep)
    • stop-the-world 시간을 줄이기 위해 고안됨
    • compact 과정이 없음

 

References

 

[JAVA] 자바 가비지 컬렉션 , Java Garbage Collection #GC

자바 가비지 컬렉션 , Java Garbage Collection 안녕하세요? 장장스입니다. 자바의 GC에 대해 정리해보겠습니다. GC (Garbage Collection) 자바 어플리케이션은 JVM에 의해 구동이 됩니다. GC(Garbage Collection)는 JVM

zangzangs.tistory.com

 

'개발 > Java' 카테고리의 다른 글

System.out.println() 사용 안하는 이유  (0) 2022.12.14
String, StringBuilder, StringBuffer  (0) 2022.12.13
equals()  (0) 2022.11.30
[자바/JAVA] 정적 변수와 메서드 (static)  (0) 2021.06.25
[자바/JAVA] this  (0) 2021.06.24
반응형

자바의 최상위 클래스인 Object 클래스에는 여러가지 native 메서드가 존재하는데

그 중 equals()에 대해 알아보고자 한다.

 

1. equals() 란?

Object 클래스에서는 단순히 "동일한" 객체인지 비교. (동일성)

public boolean equals(Object obj) {
    return (this == obj);
}

equals() 는 보통 하위 클래스에서 재정의하여 사용하는데, 보통 "동등성"을 비교.

 

대표적인 예시로, String 클래스의 equals() 들 수 있다.

String의 equals()는 문자열을 비교하기 위해, 해당 문자열의 "내용"을 비교하도록 재정의 되어있다.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

 

2. == 연산자와의 차이점

"==" 연산자는 primitive type에 대해서는 값을 비교, reference type에 대해서는 주소값을 비교한다.

사실 primitive type에서도 Constant Pool에 있는 특정 상수값을 참조하는 것이기 때문에, 결국 주소값을

비교하는 연산자라고 볼 수 있다.

 

Object의 equals()와 동일한 기능을 하고 있다고 볼 수 도 있다.

다만 == 연산자의 경우 재정의하여 사용하지 않고, 오직 동일성 비교를 위해서 사용된다고 보면된다.

 

다음 예제로 == 연산자와 String 클래스의 equals() 메서드를 비교해보자.

public class Main {
    public static void main(String[] args) {
        String str1 = "apple";
        String str2 = new String("apple");

        System.out.println(str1.equals(str2)); // true
        System.out.println(str1 == str2); // false
    }
}

 

내부 값 자체를 비교하도록 재정의 되어있는 String 클래스의 equals() 같은 경우,

리터럴 방식으로 선언된 str1과 new로 선언된 str2의 주소값이 다르더라도, 같은 문자열이기 때문에 true가 반환된다.

 

== 연산자의 경우, str1과 str2의 주소값 자체를 비교하므로 false를 반환하게 된다.

반응형

1. 정적(static) 멤버란?

 - Static변수와 Static메소드를 합쳐 정적 멤버라고 한다. (또는 클래스 멤버)

 - 클래스에 소속된 멤버로 인스턴스 생성 여부에 상관없이 모든 인스턴스에서 공통으로 사용한다.

 

2. 정적(static) 멤버 특징

 - Static 키워드를 통해 생성된 정적 멤버들은 Heap 영역이 아닌 Static 영역에 할당된다.

 - Static 영역에 할당된 메모리는 인스턴스 생성과는 별개로 모든 객체가 공유하여 사용할 수 있는 장점이 있다.

   (Gabage Collector의 관리 영역 밖에 존재하기 때문에 Static을 남발하게 되면 시스템 성능에 문제가 생길 수 있다.)

 

3. 정적(static) 멤버 vs 인스턴스 멤버

 - 필드 혹은 메서드 생성시 정적으로 생성할 것인지, 인스턴스로 생성할 것인지에 대한 판단 기준은 공용으로 사용

   하느냐 아니냐로 판단하면 된다.

 

4. 정적(static) 멤버 사용 예시

 - 정적 필드

class Number{
    static int num = 0; //클래스 필드
    int num2 = 0; //인스턴스 필드
}

public class Static_ex {
	
    public static void main(String[] args) {
    	Number number1 = new Number(); //첫번째 number
    	Number number2 = new Number(); //두번쨰 number
    	
    	number1.num++; //클래스 필드 num을 1증가시킴
    	number1.num2++; //인스턴스 필드 num을 1증가시킴
    	System.out.println(number2.num); //두번째 number의 클래스 필드 출력
    	System.out.println(number2.num2); //두번째 number의 인스턴스 필드 출력
    }
}

 

- 정적 메서드 (정적 메소드는 유틸리티 함수를 만드는데 유용하게 사용)

class Name{
    static void print() { //클래스 메소드
	System.out.println("내 이름은 홍길동입니다.");
    }

    void print2() { //인스턴스 메소드
	System.out.println("내 이름은 이순신입니다.");
    }
}

public class Static_ex {
	
    public static void main(String[] args) {
        Name.print(); //인스턴스를 생성하지 않아도 호출이 가능
    	
        Name name = new Name(); //인스턴스 생성
        name.print2(); //인스턴스를 생성하여야만 호출이 가능
    }
}

 

 

참고) https://coding-factory.tistory.com/524

'개발 > Java' 카테고리의 다른 글

String, StringBuilder, StringBuffer  (0) 2022.12.13
[Java] Garbage Collection(가비지 컬렉션)  (2) 2022.12.02
equals()  (0) 2022.11.30
[자바/JAVA] this  (0) 2021.06.24
[자바/JAVA] 생성자와 초기화  (0) 2021.06.23
반응형

1. this란

 - this는 자기 자신을 의미하는 키워드

 - 필드(전역변수)와 메서드or생성자의 매개변수가 동일할때 인스턴스 필드임을 명시하기 위해 사용한다.

 

2. this 특징

 - 전역변수(인스턴스 필드)와 지역변수(매개변수) 구분

class Student{
    String name; // 인스턴스 필드(전역변수)
    int age; 
    
    Student(String name, int age){
        this.name = name; // this.name는 인스턴스 필드 / name는 매개변수를 의미
        this.age = age; // this.name는 인스턴스 필드 / name는 매개변수를 의미
    }
}

 - static 메서드에서는 this를 사용하지 못한다.

 - 인스턴스 멤버(메소드, 필드)는 인스턴스를 생성해야지만 사용이 가능하다.(클래스멤버와의 차이점)

 - 매개변수와 필드의 변수명이 다른 경우 굳이 this를 쓰지 않아도 된다.

 

3. this와 this()의 차이점

class Student{
    String name; // 인스턴스 필드(전역변수)
    int age; 
    
    Student(){
        this("철수", 4); // Student(String name, int age) 생성자를 호출
    }
    
    Student(String name){
        this(name, 4); // Student(String name, int age) 생성자를 호출
    }
    
    Student(String name, int age){
        this.name = name; 
        this.age = age;
    }
}

 - this()는 같은 클래스의 다른 생성자를 호출할 때 사용하는 키워드

 - 생성자 오버로딩시에 this()를 이용한 중복코드 제거 가능

 

4. this를 사용하는 이유

 - 소스가 복잡해지고 방대해지면, 변수를 관리하기 힘들고, 필드와 매개변수를 동일하게 정의하여 this로 구분하는 것이

   직관적이고 편리하다.

'개발 > Java' 카테고리의 다른 글

String, StringBuilder, StringBuffer  (0) 2022.12.13
[Java] Garbage Collection(가비지 컬렉션)  (2) 2022.12.02
equals()  (0) 2022.11.30
[자바/JAVA] 정적 변수와 메서드 (static)  (0) 2021.06.25
[자바/JAVA] 생성자와 초기화  (0) 2021.06.23
반응형

1. 생성자란?

 - 생성자는 new 연산자를 통해 객체를 생성할 때, 제일 먼저 반드시 호출되는 일종의 메서드

 

2. 생성자의 역할

 - 생성된 인스턴스를 초기화한다. (멤버 변수 초기화)

 

3. 생성자 선언 방법

  public 클래스명(매개변수) {

            ...

  }

 - 클래스명은 필수로 입력해야 하고,  접근제어자나 매개변수는 생략 가능하다.

 

4. 생성자 특징

 - 생성자를 정의하지 않더라도, 컴파일러가 자동으로 기본 생성자(Default Constructor)를 생성해준다.

public class Student {

	String name;
	int age;
	
	// public Student() {} // Default 생성자가 자동 생성 되므로 생략 가능
	
	public static void main(String[] args) {
		Student student = new Student(); // 컴파일러가 생성한 기본 생성자를 통한 인스턴스 생성
		
		student.name = "홍길동";
		student.age = 18;
		
		System.out.println("학생 이름: " + student.name + ", 학생 나이: " + student.age);
	}
}

 

 - 생성자는 매개변수를 다르게 지정하여 여러개의 생성자를 정의하는 것이 가능하다. (생성자 오버로딩)

 

 - 기본 이외의 생성자를 정의한 경우, 기본 생성자를 사용하려면 기본 생성자도 정의해줘야 한다. (컴파일 에러남)

public class Student {

	String name;
	int age;
	
	public Student(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	public static void main(String[] args) {
		Student student = new Student("홍길동", 18); // 매개변수를 가진 생성자를 통한 Student 인스턴스 생성
		
		// Student student2 = new Student(); // 사용자가 매개변수를 가진 생성자를 정의했으므로, 기본 생성자가 자동으로 생성되지 않아 컴파일 에러가 발생

		System.out.println("학생 이름: " + student.name + ", 학생 나이: " + student.age);
	}
}

 

 - 메서드와의 차이점은 반환 값이 없는 것이다. (void나 return 자료형 생략)

 

5. 매개변수를 가진 생성자를 활용한 예시

- 주문매체(orderMedia)에 따른 멤버 변수 초기화

@Getter
@ToString
public class Media {

	String orderMedia;
	String mediaCode;
	String mediaGb;
	String insertId;
	String receiveMethod;
	String membGb;
	String custNo;
	
	public Media(OrderMedia media, String membGb, String custNo) {
		switch (media) {
		case MC:
			this.orderMedia = OrderMedia.MC.toString();
			this.mediaCode = MediaCode.MC.toString();
			this.mediaGb = MediaGb.MC.toString();
			this.insertId = InsertId.MC.toString();
			this.receiveMethod = ReceiveMethod.MC.toString();
			break;
		default:
			this.orderMedia = OrderMedia.PC.toString();
			this.mediaCode = MediaCode.PC.toString();
			this.mediaGb = MediaGb.PC.toString();
			this.insertId = InsertId.PC.toString();
			this.receiveMethod = ReceiveMethod.PC.toString();
			break;
		}
		
		this.membGb = membGb;
		this.custNo = custNo;
	}
}

- 기본 생성자 사용시, 객체 생성시마다 아래의 분기문을 처리해줘야 하지만 매개변수를 가진 생성자를 통해 생성과 함께 초기화가 가능하다.

 

 

참고)

https://velog.io/@lshjh4848/%ED%81%B4%EB%9E%98%EC%8A%A4%EC%99%80-%EC%83%9D%EC%84%B1%EC%9E%90

 

클래스와 생성자

객체지향의 기본이라고 할 수 있는 클래스와 생성자에 대한 기본개념입니다.

velog.io

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=heartflow89&logNo=220955879645 

 

[JAVA/자바] 생성자(Constructor)와 초기화

이전 포스팅에서 인스턴스를 생성할 때 "클래스 객체변수 = new 클래스();" 라는 구문을 사용하고 이때 "클...

blog.naver.com

 

'개발 > Java' 카테고리의 다른 글

String, StringBuilder, StringBuffer  (0) 2022.12.13
[Java] Garbage Collection(가비지 컬렉션)  (2) 2022.12.02
equals()  (0) 2022.11.30
[자바/JAVA] 정적 변수와 메서드 (static)  (0) 2021.06.25
[자바/JAVA] this  (0) 2021.06.24

+ Recent posts