자바 에 메모리 누 출 이 있 습 니까?

4696 단어
메모리 유출 이란 프로그램 이 사용 하지 않 는 대상 이나 변수 가 메모리 에 계속 차지 되 는 것 을 말한다.자바 에는 쓰레기 회수 메커니즘 이 있 습 니 다. 대상 이 더 이상 인용 되 지 않 을 때, 즉 대상 이 고 아 를 프로 그래 밍 할 때 대상 은 자동 으로 쓰레기 회수 기 에 의 해 메모리 에서 지 워 집 니 다.자바 가 그림 에 있 는 방식 으로 쓰레기 회수 관 리 를 하기 때문에 인용 순환 의 문 제 를 없 앨 수 있 습 니 다. 예 를 들 어 두 개의 대상 이 서로 참조 되 고 루트 프로 세 스 와 도달 할 수 없 으 면 GC 도 이들 을 회수 할 수 있 습 니 다. 예 를 들 어 아래 코드 는 이러한 상황 의 메모리 회수: package com. huawei. interview 를 볼 수 있 습 니 다.
import java.io.IOException;
public class GarbageTest {
/**
 * @param args
 * @throws IOException 
 */
public static void main(String[] args) throws IOException {
    // TODO Auto-generated method stub
    try {
        gcTest();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("has exited gcTest!");
    System.in.read();
    System.in.read();       
    System.out.println("out begin gc!");        
    for(int i=0;i<100;i++)
    {
        System.gc();
        System.in.read();   
        System.in.read();   
    }
}

private static void gcTest() throws IOException {
    System.in.read();
    System.in.read();       
    Person p1 = new Person();
    System.in.read();
    System.in.read();       
    Person p2 = new Person();
    p1.setMate(p2);
    p2.setMate(p1);
    System.out.println("before exit gctest!");
    System.in.read();
    System.in.read();       
    System.gc();
    System.out.println("exit gctest!");
}

private static class Person
{
    byte[] data = new byte[20000000];
    Person mate = null;
    public void setMate(Person other)
    {
        mate = other;
    }
}

}
자바 의 메모리 유출 상황: 수명 주기 대상 이 짧 은 수명 주기 대상 의 인용 을 가지 고 있 으 면 메모리 유출 이 발생 할 수 있 습 니 다. 짧 은 수명 주기 대상 이 더 이상 필요 하지 않 지만 수명 주기 대상 이 가지 고 있 는 인용 으로 인해 회수 되 지 못 합 니 다. 이것 이 바로 자바 에서 메모리 유출 이 발생 하 는 장면 입 니 다. 쉽게 말 하면...즉, 프로그래머 가 대상 을 만 들 었 을 수도 있 습 니 다. 이후 에 이 대상 을 사용 하지 않 을 수도 있 습 니 다. 이 대상 은 계속 인용 되 었 습 니 다. 즉, 이 대상 은 쓸모 가 없 지만 쓰레기 회수 기 에 의 해 회수 되 지 못 합 니 다. 이것 은 자바 에서 메모리 가 유출 될 수 있 는 상황 입 니 다. 예 를 들 어 캐 시 시스템, 우 리 는 대상 을 캐 시 에 불 러 왔 습 니 다 (예 를 들 어 전체 map 대상 에 두 었 습 니 다).그리고 더 이상 사용 하지 않 습 니 다. 이 대상 은 캐 시 에 인용 되 었 으 나 더 이상 사용 되 지 않 습 니 다.자바 의 메모리 유출 을 확인 하려 면 프로그램 이 프로그램 이 끝 날 때 까지 여러 가지 상황 을 완전 하 게 실행 한 다음 에 어떤 대상 이 사용 되 었 는 지 확인 하고 없 으 면 이 대상 이 메모리 유출 에 속 하 는 지 판단 할 수 있 습 니 다.
만약 에 외부 클래스 의 인 스 턴 스 대상 방법 이 내부 클래스 의 인 스 턴 스 대상 을 되 돌려 준다 면 이 내부 클래스 대상 은 장기 적 으로 인용 되 었 습 니 다. 비록 외부 클래스 의 인 스 턴 스 대상 이 더 이상 사용 되 지 않 더 라 도 내부 클래스 의 지속 적 인 외부 클래스 의 인 스 턴 스 대상 으로 인해 이 외부 클래스 의 대상 은 쓰레기 로 회수 되 지 않 고 메모리 가 유출 될 수 있 습 니 다.
아래 내용 은 인터넷 에서 나 온 것 입 니 다. (주요 특징 은 스 택 의 특정한 요 소 를 비 우 는 것 입 니 다. 이 요 소 를 배열 에서 완전히 제거 하 는 것 이 아니 라 저장 한 총 수 를 줄 이 는 것 입 니 다. 본인 은 이것 보다 잘 쓸 수 있 습 니 다. 특정한 요 소 를 제거 하 는 동시에 배열 에서 사라 지게 하고 그 요소 가 있 는 위치의 값 을 null 로 설정 하면 됩 니 다): 저 는 그 창고 보다 더 전형 적 인 예 를 생각 하지 못 했 습 니 다. 그래서 저 는 다른 사람의 예 를 인용 해 야 합 니 다. 다음 의 예 는 제 가 생각 한 것 이 아니 라 책 에서 본 것 입 니 다. 물론 책 에서 보지 않 았 다 면 시간 이 지나 면 저도 생각 했 을 것 입 니 다. 그런데 그때 저 는 제 가 생각 한 것 이 라 고 말 했 고 아무 도 믿 지 않 았 습 니 다.public class Stack { private Object[] elements=new Object[10]; private int size = 0; public void push(Object e){ ensureCapacity(); elements[size++] = e; } public Object pop(){ if( size == 0) throw new EmptyStackException(); return elements[--size]; } private void ensureCapacity(){ if(elements.length == size){ Object[]oldElements = elements; elements = new Object [2 * elements. length + 1]; System. arraycopy (oldElements, 0, elements, 0, size);}}} 위의 원 리 는 간단 할 것 입 니 다. 스 택 에 10 개의 요 소 를 추가 한 후에 모두 튕 겨 나 오 면 스 택 이 비어 있 고 우리 가 원 하 는 것 이 없 지만 대상 은 회수 할 수 없습니다.이것 이 야 말로 메모리 유출 의 두 가지 조건 에 부합된다. 쓸모 가 없고 회수 할 수 없다.그러나 이런 물건 이 존재 한다 고 해서 반드시 어떤 결 과 를 초래 할 수 있 는 것 은 아니다. 만약 에 이 스 택 이 비교적 적 게 사용 하면 K 메모리 몇 개 를 낭비 할 뿐이다. 어차피 우리 의 메모리 가 G 에 올 랐 으 니 어디 에 영향 이 있 을 까? 그리고 이 물건 은 곧 회수 되 고 무슨 관계 가 있 을 까?다음은 두 가지 예 를 보 겠 습 니 다.예 1 public class Bad {public static Stack s = Stack (), static {s. push (new Object), s. pop (), / / 여기에 메모리 유출 s. push (new Object () 가 발생 했 습 니 다. / / 위의 대상 을 회수 할 수 있 습 니 다.} static 이기 때문에 프로그램 이 종 료 될 때 까지 존재 하지만 치유 기능 이 있 는 것 도 볼 수 있 습 니 다.즉, 만약 당신 의 Stack 이 최대 100 개의 대상 이 있다 면 최대 100 개의 대상 만 회수 되 지 못 할 것 입 니 다. 사실은 이것 은 쉽게 이해 할 수 있 을 것 입 니 다. Stack 내부 에 100 개의 인용 을 가지 고 있 습 니 다. 최 악의 경 우 는 그들 이 모두 쓸모 가 없다 는 것 입 니 다. 왜냐하면 우리 가 새로운 진취 적 인 것 을 넣 으 면 앞의 인용 은 자 연 스 럽 게 사라 지기 때 문 입 니 다!
메모리 유출 의 또 다른 상황: 한 대상 이 HashSet 집합 에 저 장 된 후에 이 대상 의 해시 값 계산 에 참여 하 는 필드 를 수정 할 수 없습니다. 그렇지 않 으 면 대상 이 수정 한 해시 값 은 HashSet 집합 에 처음 저 장 된 해시 값 과 다 릅 니 다. 이러한 상황 에서contains 방법 에서 이 대상 의 현재 인용 을 매개 변수 로 HashSet 집합 에서 검색 대상 을 사용 하 더 라 도 대상 을 찾 을 수 없 는 결 과 를 되 돌려 줍 니 다. 이 는 HashSet 집합 에서 현재 대상 을 따로 삭제 하지 못 해 메모리 가 유출 될 수 있 습 니 다.

좋은 웹페이지 즐겨찾기