2023. 2. 20. 16:25ㆍJava
프로젝트 내 src 내 javabasic 패키지 내 JdbcEx4.java
package javabasic;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcEx4 {
public static void main(String[] args) throws Exception {
Connection c;
// TODO Auto-generated method stub
Class.forName("oracle.jdbc.driver.OracleDriver");
c = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "a1234");
System.out.println("접속 완료!!!");
Statement st = c.createStatement();
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String sql = "";
System.out.println("질의문을 입력하세요.....");
while ((sql = buf.readLine()) != null) {
Boolean bool = st.execute(sql);
ResultSet rs = null;// 결과셋이있는지없는지알수없기때문에널
int upCnt = 0;// update카운트있는지없는지알수없기때문에0
if (bool) {// 참이면 ResultSet 에 return값이 생성이된다
rs = st.getResultSet();
while (rs.next()) {
int no = rs.getInt("no");
String name = rs.getString("name");
String hp = rs.getString("hp");
String addr = rs.getString("addr");
System.out.println(no + " " + name + " " + hp + " " + addr);
}
if (rs != null)
rs.close();
// close() 메서드는 자원을 해제하는 것이다.
// ResultSet 클래스 객체인 rs 라는 변수가 처음에는 null 을
// 가리킨다. 그 후에는 어떤 구체적인 값을 대입받아 그 값을 가리키게
// 된다. 그런데 while 문에서 다시 처음부터 실행되려고 돌아갈 때
// ResultSet 변수 rs 를 한번 더 null 값을 가리키게 한다.
// null 값을 가리키게 한다고 자원해제가 바로 되는 것이 아니다.
// Java 에서는 garbage collector 가 있어서
// 변수가 참조하던 A값에서 B값으로 참조변경을 하면
// Garbage Collector 가 A값을 쓰레기값으로 생각하고
// 처리를 해주는 듯 하다..
// 그렇지만 Gargabe Collector 가 있고 null 값을 할당한다고
// 해서 Garbage Collector 가 모든 자원을 해제하는 것은
// 아니다. 명시적으로 해제를 해야 할 경우가 있다. 대표적인 것이
// 파일을 열고 닫을 때 db 커넥션을 열고 닫을 때는 Garbage Collector
// 에 의해 처리 되지 않아서, rs 를 자원해제 하지 않으면
// rs 변수에 대입되었었던 어떤 값이 쓰레기값으로 인식되지않아
// 그냥 계속 남은 상태로 null 값이 그다음에 대입이 되고
// 계속해서 while 문을 돌면서 rs 변수에 대입되었었던 값들이
// 메모리에 쓰레기 처럼 남아서 메모리를 독점하게 되면
// 운영체제의 자원이 고갈되어 다른 프로그램은 운영체제의 자원을
// 사용하지 못하게 되는 결과를 초래한다.
// 명시적으로 close() method 를 써서 자원을 반환해아 한다.
} else {
upCnt = st.getUpdateCount();
System.out.println(upCnt + "개의 로우가 변경되었습니다..!");
}
} // while문
if (buf != null)
buf.close();
if (st != null)
st.close();
if (c != null)
c.close();
}
}
실행 결과
접속 완료!!!
질의문을 입력하세요.....
select * from member
1 홍길동 010-1111-1111 서울시 종로구 흥인동
3 안다미 010-1111-2131 서울시 관악구 신림동
7 김나래 010-1111-2121 서울시 송파구 잠실새내동
4 김지성 010-1111-9121 서울시 강동구 상일동
5 박만구 010-1121-9121 경기도 하남시 미사동
2 임수영 010-2121-9121 서울시 은평구 한옥마을
update member set name = '임평화' where no = 2
1개의 로우가 변경되었습니다..!
select * from member
1 홍길동 010-1111-1111 서울시 종로구 흥인동
3 안다미 010-1111-2131 서울시 관악구 신림동
7 김나래 010-1111-2121 서울시 송파구 잠실새내동
4 김지성 010-1111-9121 서울시 강동구 상일동
5 박만구 010-1121-9121 경기도 하남시 미사동
2 임평화 010-2121-9121 서울시 은평구 한옥마을
insert into member values(6, '남보라', '010-333-2323', '경기도 성남시 분당구 서현동')
1개의 로우가 변경되었습니다..!
select * from member
6 남보라 010-333-2323 경기도 성남시 분당구 서현동
1 홍길동 010-1111-1111 서울시 종로구 흥인동
3 안다미 010-1111-2131 서울시 관악구 신림동
7 김나래 010-1111-2121 서울시 송파구 잠실새내동
4 김지성 010-1111-9121 서울시 강동구 상일동
5 박만구 010-1121-9121 경기도 하남시 미사동
2 임평화 010-2121-9121 서울시 은평구 한옥마을
insert into member values(8, '서은혜', '010-1235-2346', '서울시 종로구 종로1동')
1개의 로우가 변경되었습니다..!
select * from member
6 남보라 010-333-2323 경기도 성남시 분당구 서현동
8 서은혜 010-1235-2346 서울시 종로구 종로1동
1 홍길동 010-1111-1111 서울시 종로구 흥인동
3 안다미 010-1111-2131 서울시 관악구 신림동
7 김나래 010-1111-2121 서울시 송파구 잠실새내동
4 김지성 010-1111-9121 서울시 강동구 상일동
5 박만구 010-1121-9121 경기도 하남시 미사동
2 임평화 010-2121-9121 서울시 은평구 한옥마을
delete from member where no = 8
1개의 로우가 변경되었습니다..!
select * from member
6 남보라 010-333-2323 경기도 성남시 분당구 서현동
1 홍길동 010-1111-1111 서울시 종로구 흥인동
3 안다미 010-1111-2131 서울시 관악구 신림동
7 김나래 010-1111-2121 서울시 송파구 잠실새내동
4 김지성 010-1111-9121 서울시 강동구 상일동
5 박만구 010-1121-9121 경기도 하남시 미사동
2 임평화 010-2121-9121 서울시 은평구 한옥마을
boolean java.sql.Statement.execute(String sql) throws SQLException
execute(String sql) 메서드는
다수의 결과들을 반환할 수 있는 주어진 SQL 문을 실행한다.
execute 메서드는 SQL 문을 실행한 다음에 그 첫번째 결과의 form(모양) 을 가리킨다. 개발자는 반드시 그러면 그 결과라는 정보를 끌어내오기 위해서 getResultSet 메소드라던가 getUpdateCount 메소드를 사용해야만 하고, 아무 뒤위(후속의) 결과(결과들)로 이동시키기 위해서 getMoreResults 메서드를 사용해야만 한다.
execute(String sql) 메서드는
만약에 그 첫번째 결과가 ResultSet 객체라면 true 를 반환한다; 만약에 그 첫번째 결과가 update(새롭게한일) 횟수이거나 어떠한 결과도 없다면 false 를 반환한다.
Garbage Collection
프로그램을 개발 하다 보면 유효하지 않은 메모리인 Garbage 가 발생하게 된다. C언어를 이용하면 free() 메서드를 사용해 직접 메모리를 해제해 주어야 한다. 하지만 Java 를 사용한다면 개발자는 메모리를 직접 해제해 주는 일이 없다. 왜냐하면 JVM 의 Garbage Collector 가 불필요한(유효하지 않은) 메모리를 알아서 정리해 주기 때문이다. 대신 Java 에서 명시적으로 불필요한 데이타를 표현하기 위해서 일반적으로 null 을 선언해준다.
Person person = new Person();
person.setName("Mang");
person = null;
// 가비지 발생
person = new Person();
person.setName("MangKyu");
기존의 Mang 이라는 이름으로 생성된 person 객체는 더 이상 참조를 하지 않고 사용이 되지 않아서 없어지지는 않은 상태로 메모리에 쓰레기처럼 남아서 Garbage 가 되었다. 왜냐하면 person = null; 문을 쓰면서 명시적으로 불필요한(유효하지 않은) 데이타라는 것을 표현해 주었기 때문이다. Java 에서는 이렇게 하면 Mang 이름으로 생성된 person 객체가 메모리에 쓰레기처럼 불필요한 존재로 남고 그런 것을 메모리 누수라고 하며, 이러한 메모리 누수를 방지하기 위해 Garbage Collector 가 주기적으로 메모리 검사를 하여 메모리를 청소해 준다고 한다. Java 에서도 System.gc() 를 이용해 호출할 수 있지만, 해당 메서드를 호출하는 것은 시스템의 성능에 매우 큰 영향을 미쳐서 절대 호출해서는 안된다고 한다.
JVM 의 Heap 영역은 처음 설계될 때 다음의 2가지를 전제로 설계되었다고 한다.
1. 대부분의 객체는 금방 접근 불가능한 상태가 된다.
2. 오래된 객체에서 새로운 객체로의 참조는 아주 적게 존재한다.
즉, 객체는 대부분 일회성이며, 메모리에 오랫동안 남아있는 경우는 드물다고 한다. 그래서 객체의 생존 기간에 따라 물리적인 Heap 영역을 나누게 되었고 Young, Old 2가지 영역으로 설계되었다고 한다. 초기에는 Perm 영역이 있었지만 Java8 부터 제거되었다고 한다.
Young 영역(Young Generation)
1. 새롭게 생성된 객체가 할당되는 영역
2. 대부분의 객체가 금방 Unreachable 상태가 되므로, 많은 객체가 Young 영역에 생성되었다고 사라진다고 한다.
3. Young 영역에 대한 Garbage Collection 을 Minor GC(Garbage Collector) 라고 부른다고 한다.
Old 영역(Old Generation)
1. Young 영역에서 Reachable 상태를 유지하여 살아남은 객체가 복사되는 영역
2. Young 영역보다 크게 할당되며, 영역의 크기가 큰 만큼 Garbage 는 적게 발생한다고 한다.
3. Old 영역에 대한 Garbage Collection 을 Major GC 또는 Full GC 라고 부른다고 한다.
Old 영역이 Young 영역보다 크게 할당되는 이유는 Young 영역의 수명이 짧은 객체들은 큰 공간을 필요로 하지 않으며 큰 객체들은 Young 영역이 아니라 바로 Old 영역에 할당되기 때문이라고 한다.
Garbage Collection 의 동작 방식
Young 영역과 Old 영역은 서로 다른 메모리 구조로 되어 있기 때문에 세부적인 동작 방식이 다르다고 하다. 하지만 기본적으로 Garbage Collection 이 실행된다 하면 다음의 2가지 공통적 단계를 따른다고 한다.
1. Stop The World
2. Mark and Sweep
1. Stop The World
Stop The World 는 Garbage Collection 을 실행하기 위해 JVM 이 Application 의 실행을 멈추는 작업이라고 한다. GC 가 실행될 때는 GC 를 실행하는 스레드를 제외한 모든 스레드들의 작업이 중단되고, GC 가 작업이 완료되면 작업이 재개된다고 한다. 당연히 모든 스레드들의 작업이 중단되면 Application 이 멈추기 때문에, GC 의 성능 개선을 위해 Tuning 을 한다고 하면 보통 Stop The World 의 시간을 줄이는 작업을 한다고 한다.
2. Mark and Sweep
Mark: 사용되는 메모리와 사용되지 않는 메모리를 식별하는 작업
Sweep: Mark 단계에서 사용되지 않음으로 식별된 메모리를 해제하는 작업
Stop The World 를 통해 모든 작업을 중단시키면, GC 는 스택의 모든 변수 또는 Reachable 객체를 스캔하면서 각각이 어떤 객체를 참고하고 있는지를 탐색하게 된다고 한다. 그리고 사용되고 있는 메모리를 식별하는데, 이 과정을 Mark 라고 한단다. 이후에 Mark 가 되지 않은 객체들을 메모리에서 제거하는데 요 과정은 Sweep 이라고한다.
Minor GC 의 동작 방식
Young 영역은 1 개의 Eden 영역과 2개의 Survivor 영역, 총 3가지로 나뉜다.
Eden 영역: 새로 생성된 객체가 할당되는 영역
Survivor 영역: 최소 1번 이상의 GC 작업 이후 살아남은 객체가 존재하는 영역
객체가 새롭게 생성되면 Young 영역 중에서도 Eden 영역에 할당된다. 그리고 Eden 영역이 꽉 차면 Minor GC 이 발생하게 되는데, 사용되지 않는 메모리는 해제되고 Eden 영역에 존재하는 객체는 (사용중인 메모리를 뜻한다) Survivor 영역으로 옮겨진다. Survivor 영역은 총2개이지만 반드시 1개의 영역에만 데이타가 존재해야 하는데, Young 영역의 동작 순서는 다음과 같다.
1. 새로 생성된 객체가 Eden 영역에 할당된다.
2. 객체가 계속 생성되어 Eden 영역이 꽉 차게 되고 Minor GC 이 실행된다.
2-1. Eden 영역에서 사용되지 않는 객체의 메모리가 해제된다.
2-2. Eden 영역에서 살아남은 객체는 1개의 Survivor 영역으로 이동된다.
3. 1~2번의 과정이 반복되다가 Survivor 영역이 가득 차게 되면 Survivor 영역의 살아남은 객체를 다른 Survivor 영역으로 이동시킨다. (1개의 Survivor 영역은 반드시 빈 상태가 된다.)
4. 이러한 과정을 반복하여 계속해서 살아남은 객체는 Old 영역으로 이동(Promotion) 된다.
객체의 생존 횟수를 세기 위해 Minor GC 에서 객체가 살아남은 횟수를 의미하는 age 를 Object Header 에 기록한다. 그리고 Minor GC 을 할 때 Object Header 에 기록된 age 를 보고 Promotion 여부를 결정한다고 한다.
또한 Survivor 영역 중 1개는 반드시 사용이 되어야 한다. 만약 두 Survivor 영역에 모두 데이타가 존재하거나, 모두 사용량이 0 이라면 현재 시스템이 정상적인 상황이 아님을 파악할 수 있다고 한다.
Major GC 의 동작 방식
Young 영역에서 오래 살아남은 객체는 Old 영역으로 Promotion 됨을 확인할 수 있었다. 그리고 Major GC 은 객체들이 계속 Promotion 되어 Old 영역의 메모리가 부족해지면 발생한다. Young 영역은 일반적으로 Old 영역보다 크기가 작기 때문에 GC 이 보통 0.5초에서 1초 사이에 끝난다고 한다. 그래서 Minor GC 은 Application 에 크게 영향을 안준다. 허나 Old 영역은 Young 영역보다 크며 Young 영역을 참조할 수도 있다. 그래서 Major GC 은 일반적으로 Minor GC 보다 시간이 오래걸리고 10배 이상의 시간을 사용한다고 한다.
https://mangkyu.tistory.com/118
[Java] Garbage Collection(가비지 컬렉션)의 개념 및 동작 원리 (1/2)
1. Garbage Collection(가비지 컬렉션)이란? [ Garbage Collection(가비지 컬렉션)이란? ] 프로그램을 개발 하다 보면 유효하지 않은 메모리인 가바지(Garbage)가 발생하게 된다. C언어를 이용하면 free()라는 함
mangkyu.tistory.com
'Java' 카테고리의 다른 글
Java Collections class (0) | 2023.02.21 |
---|---|
Java executeUpdate() (0) | 2023.02.20 |
Java executeQuery(String sql) (0) | 2023.02.20 |
Java while 문 무한 loop 종료 (0) | 2023.02.20 |
Java createStatement() (1) | 2023.02.20 |