JavaRush /Java Blog /Random-KO /커피 브레이크 #88. 메타데이터의 힘: 스파게티 코드로 작업하는 방법 Java의 가비지 수집 - 작동...

커피 브레이크 #88. 메타데이터의 힘: 스파게티 코드로 작업하는 방법 Java의 가비지 수집 - 작동 방식 및 장점

Random-KO 그룹에 게시되었습니다

메타데이터의 힘: 스파게티 코드로 작업하는 방법

출처: Hackernoon 우리 모두는 일반적인 접근 방식과 알려진 패턴을 사용하여 최소한의 노력과 최대의 영향으로 애플리케이션을 만들려고 노력합니다. 우리는 일상적인 작업을 수행하는 뛰어난 라이브러리와 강력한 프레임워크를 보유하고 있습니다. 우리는 이 모든 것을 비즈니스 로직에만 집중하기 위해 사용합니다. 그러나 이러한 추구는 특히 기성 솔루션 없이 기능을 구현하는 경우 스파게티 코드로 이어지는 경우가 많습니다. 이 기사에서는 내 경험상 모든 개발자가 높이 평가하지는 않는 강력한 도구 하나를 여러분과 공유하고 싶습니다. 이 도구는 대부분의 프로그래밍 언어에 존재하며 주석과 같은 많은 프레임워크에서 자주 사용됩니다. 커피 브레이크 #88.  메타데이터의 힘: 스파게티 코드로 작업하는 방법  Java의 가비지 수집 - 작동 방식 및 장점 - 1

스파게티를 좋아하시나요?

몇 년 전에 제가 접한 예를 살펴보겠습니다. 구문 분석된 데이터를 데이터베이스에 저장하려면 Excel 스프레드시트를 구문 분석해야 했습니다. 또한 데이터베이스에서 일부 데이터를 수집하여 스프레드시트를 만들고 싶었습니다. 구현을 위해 잘 알려진 Java 라이브러리인 Apache POI를 사용했습니다. 라이브러리의 API를 사용하면 시트, 행, 셀 및 기타 요소를 수동으로 만들 수 있으므로 작업이 더 쉬워집니다. 이는 매우 좋지만 다양한 Excel 스프레드시트를 생성해야 하는 경우 코드를 전혀 읽을 수 없고 지원할 수 없게 됩니다. 결과적으로 일반적으로 발생하는 것처럼 응용 프로그램의 첫 번째 버전은 단순히 끔찍한 것으로 나타났습니다. 구현은 구문 분석에 필요한 모든 필드가 포함된 문자열을 나타내는 데이터 클래스로 구성되었습니다. Excel 필드를 셀별로 구문 분석하여 새로 생성된 데이터 클래스 인스턴스에 배치하는 파서도 있었습니다. 처음에는 프로그램이 훌륭하게 작동했고 필요한 작업을 수행했습니다. 일부 수정이 필요할 때 문제가 시작되었습니다. 코드를 읽지 못했습니다. 이 코드를 작성한 나조차도 나에게 필요한 새로운 기능을 구현하기 위해 새 줄을 배치할 적절한 장소를 찾지 못했습니다.

주석으로 구조하기

이 주석 스파게티 코드에서 애플리케이션을 저장했습니다. 지원되지 않는 코드를 제거하려면 구문 분석할 열, 셀에 포함된 데이터 유형 및 기타 모든 항목을 결정하는 논리를 다른 위치로 이동해야 했습니다. 이를 위해 각 클래스 필드에 대한 열 이름을 지정하는 주석을 만들었습니다. 주석에는 셀의 색상과 글꼴을 선택할 수 있는 변수도 추가했습니다. 따라서 구문 분석 클래스의 코드가 크게 줄었습니다. 단 하나의 프로세서만이 주석에서 가져온 매개변수를 기반으로 스프레드시트를 동적으로 생성했습니다. 그것은 승리였습니다. 그런 다음 애플리케이션을 변경하려면 주석이 포함된 클래스를 만들어야 했습니다. 이 솔루션은 주석을 사용하여 JSON을 구문 분석하는 Jackson 라이브러리를 연상시켰으며 Jackson이나 유사한 라이브러리가 얼마나 편리한지는 말할 필요가 없다고 생각합니다.
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnExcel {

    String name() default "";

    int position();

    ExcelColumnDataFormat cellTypePattern() default ExcelColumnDataFormat.NONE;

    IndexedColors cellColor() default IndexedColors.AUTOMATIC;

    ExcelTotalFormula total() default ExcelTotalFormula.NONE;

}
ColumnExcel columnExcel = field.getAnnotation(ColumnExcel.class);
애플리케이션이 발전하면서 내부에 함수가 포함된 스프레드시트의 셀을 생성하는 데 사용할 수 있는 새로운 주석이 추가되었습니다. 다양한 필드를 곱하고 뺄 수 있으며 일반적인 Excel 기능을 사용할 수 있습니다. 또한 열별로 합계를 표시하기 위해 합계 행을 추가했습니다. 그리고 메인 파서를 약간 수정하고 클래스에 주석을 추가하는 것만으로 이 모든 작업을 수행했습니다.
@ColumnExcel(
            name = "Views",
            position = 4,
            total = ExcelTotalFormula.SUM)
    private BigDecimal variableC;

    @ColumnExcelFormula(
            name = "Conversion",
            position = 5,
            cellTypePattern = CellDataTypeFormatPattern.PERCENTAGE
    )
    public String variableD(int rowNumber) {
        return new CellAddress(rowNumber, 4).formatAsString() + "*"
		+ new CellAddress(rowNumber, 2).formatAsString();
    }

    @ColumnExcelTotalFormula(position = 4, cellTypePattern = CellDataTypeFormatPattern.RUR)
    public static String getVariableCTotalFormula(int firstRowNum, int lastRowNum) {
        return "SUM( " + new CellAddress(firstRowNum, 4).formatAsString() + ":"
		+ new CellAddress(lastRowNum, 4).formatAsString() + ")";
    }

Java의 가비지 수집 - 작동 방식 및 장점

출처: Dev.to 가비지 수집이란 메모리에서 사용하지 않는 개체를 파괴하거나 정리하는 것을 의미합니다. Java는 객체가 생성되면 힙의 일부 메모리를 사용하므로 메모리 할당 해제를 자동으로 처리합니다. 커피 브레이크 #88.  메타데이터의 힘: 스파게티 코드로 작업하는 방법  Java의 가비지 수집 - 작동 방식 및 장점 - 2

어떻게 작동하나요?

Java 이전에 가장 널리 사용되는 프로그래밍 언어는 C 또는 C++였습니다. 이러한 언어를 사용한다면 해당 언어가 자체 메모리를 수동으로 관리한다는 점을 알아야 합니다. 예를 들어 C 에는 버퍼 메모리를 사용할 수 있는 calloc() , malloc()realloc() 과 같은 메서드가 있습니다 . 프로그램에 필요한 메모리 양을 결정하고 이 API에서 호출하는 항목을 지정해야 합니다. 그런 다음 연결된 목록 노드나 다른 것을 생성하기 위한 메모리 버퍼를 얻을 수 있습니다. 프로그램이 종료되면 어느 시점에서 해당 메모리를 정리할 책임도 사용자에게 있습니다. 따라서 C로 작성된 대규모 애플리케이션은 버퍼 메모리를 계속 할당하고 때때로 이를 플러시하는 것을 잊어버립니다. 이로 인해 궁극적으로 메모리 누수가 발생하고 애플리케이션에 많은 문제가 발생합니다. C 및 C++와 달리 Java 언어에는 가비지 수집기라는 스레드를 통해 자동 메모리 관리 기능이 제공됩니다. 주요 목적은 액세스할 수 없는 객체를 파괴하여 힙 메모리를 확보하는 것입니다. 가비지 수집기는 항상 백그라운드에서 실행됩니다.

Java에서 접근할 수 없는 객체는 무엇입니까?

객체는 언제 가비지 수집을 시작할 기회를 얻나요? 액세스할 수 없는 개체가 있는 경우 - 활성 링크가 없는 개체입니다. 예를 살펴보겠습니다:
public static void main(String[] args)
{
// StringBuffer object sb is not eligible for garbage collection
StringBuffer sb = new StringBuffer("Flower Brackets");
System.out.println(sb);
// StringBuffer object sb is eligible for garbage collection
sb = null;
}
기본 메서드에서는 StringBuffer 개체 와 이에 대한 참조를 만들었습니다. 이 시점에서 StringBuffer 개체는 가비지 수집에 적합하지 않습니다. 이제 StringBuffer 개체를 "null"로 설정하겠습니다 . 이제 객체는 가비지 수집 대상이 되며 힙 메모리에서 액세스할 수 없는 객체가 됩니다. 즉, 가비지 수집은 일반적으로 개체에 액세스할 수 없는 경우에 작동합니다. 이는 객체가 일반적으로 "if 블록" 또는 메서드의 컨텍스트에서 생성된다는 것을 의미합니다. 따라서 메서드 실행이 완료되면 개체는 범위를 벗어나 가비지 수집기에 의해 삭제될 수 있습니다. 이전 개체에서 새 개체에 대한 참조는 제한된 수로 존재하기 때문에 오랫동안 응용 프로그램에 존재했던 개체는 일반적으로 새로 생성된 개체가 아니라는 의미입니다. 다음은 우리가 알아야 할 몇 가지 용어입니다. 그 중 하나는 살아있는 객체입니다. 동일한 응용 프로그램의 다른 개체에서 참조하는 응용 프로그램의 개체입니다. "죽은" 개체도 있습니다. 데드 개체는 메서드 호출 중에 생성되어 액세스할 수 없는 개체이며, 메서드 호출이 완료되면 개체는 컨텍스트를 벗어나 힙에 그대로 남아 있습니다.

객체는 언제 가비지 수집 대상이 되나요?

객체에 참조 변수가 없으면 해당 객체는 가비지 수집에 적합합니다.

가비지 수집에 객체를 사용할 수 있게 만드는 방법은 무엇입니까?

다음은 여러 가지 방법입니다.
  1. null reference variable
    Student obj = new Student();
    obj = null;

  2. re-assign reference variable
    Student obj1 = new Student();
    Student obj2 = new Student();
    obj1 = obj2;

  3. reate anonymous object
    new Student();

    가비지 수집기에서 객체를 사용할 수 있게 되면 즉시 삭제되지 않습니다.

Java Virtual Machine이 가비지 수집기를 실행하면 개체만 삭제됩니다. 참고: 가비지 수집기는 "new" 키워드를 사용하여 생성된 개체만 수집합니다. "new" 키워드가 없는 개체의 경우 finalize() 메서드를 사용합니다 . Java Virtual Machine에서 가비지 수집기를 실행하는 방법에는 여러 가지가 있습니다.
  1. System.gc() 메서드

  2. finalize() 메소드

  3. Runtime.getRuntime().gc() 메서드

정적 gc() 메소드는 System 클래스 에 있습니다 . 이 메소드는 JVM에 가비지 수집기를 호출하도록 요청합니다. Java 애플리케이션이 gc() 메소드를 사용하여 가비지 수집기를 호출하는 방법을 살펴보겠습니다.
public class GarbageCollector
{
public static void main(String[] args)
{
Employee obj1 = new Employee();
Employee obj2 = new Employee();
obj1 = null;
obj2 = null;
System.gc();
}
public void finalize()
{
System.out.println("object garbage collected");
}
}
결과:
개체 가비지 수집 개체 가비지 수집됨
finalize() 메서드는 객체가 정리되기 직전에 호출됩니다. 이 메소드는 Object 클래스 에 정의되어 있습니다 .
protected void finalize() throws Throwable
  1. Finalize 메서드는 데이터베이스에 대한 연결을 닫는 데 사용됩니다.

  2. 이 메소드는 JVM이 아닌 가비지 수집기에 의해 호출됩니다.

  3. finalize() 메서드를 재정의해야 합니다 . 빈 구현이 있기 때문입니다.

  4. 개체당 한 번만 호출됩니다.

getRuntime().gc() 메서드는 런타임 클래스에 있습니다. 현재 Java 애플리케이션과 연관된 런타임 객체를 반환합니다 . Java 프로그램에서 이 메소드를 살펴보겠습니다.
public class Demo
{
public static void main(String[] args)
{
Demo obj1 = new Demo();
Demo obj2 = new Demo();
// nullifying reference variable
obj1 = null;
// nullifying reference variable
obj2 = null;
// running Garbage Collector
Runtime.getRuntime().gc();
}
@Override
protected void finalize() throws Throwable
{
System.out.println("Garbage collector called");
System.out.println("Object garbage collector: " + this);
}
}
결과:
개체 가비지 수집기라는 가비지 수집기: Demo@2130772 개체 가비지 수집기라는 가비지 수집기: Demo@cd4e940

가비지 수집의 이점:

  1. Java의 가비지 수집은 자동으로 수행되므로 사용된 메모리를 해제해야 하는 추가 부담이 줄어듭니다. 이는 Java 프로그램의 메모리를 더욱 효율적으로 만듭니다.
  2. 가비지 수집은 프로그램 무결성을 보장합니다.
  3. 가비지 수집기는 JVM의 일부이므로 추가 코드를 작성할 필요가 없습니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION