1. 자바 파일(Java File), 클래스 파일(Class File)

자바 파일이란 확장자 명이 .java인 파일로서

자바언어로 소스 코드를 작성할때 그 내용을 적는 파일이다

 

클래스 파일이란 확장자 명이 .class인 파일로서

자바 파일을 자바 컴파일러로 컴파일한 파일이 클래스 파일이다

 

여기서 컴파일러는 javac 이 된다

 

이러한 클래스파일을 자바에 클래스 로더가 JVM으로 로딩 시킨다

 

자바에서 클래스의 로딩 과정은

클래스 로더가 .class 파일의 위치를 찾아

그 파일을 JVM 위에 올려놓는 과정을 뜻한다

 

 

2. 동적 로딩

자바에서는 동적로딩을 지원한다

그래서 실행 시 모든 클래스가 로딩되지 않고

필요한 시점에 클래스를 로딩해서 사용할 수 있다

 

1) 로드 타임 동적 로딩

하나의 클래스를 로딩하는 과정에서 필요한 다른 클래스를 동적으로 로딩하는 것

 

예를들어 Hello.java 라는 자바 파일에서

System.out.println("Hello World"); 라는 코드를 작성하고

Javac으로 컴파일해 Hello.class 라는 파일을 만들었다고 보자

 

이때 Hello.class 파일만 JVM에 로딩하는게 아니라

Hello.class를 로딩하는데 필요한 System, String 관련 .class 파일들도

미리 JVM에 로딩 된다는 것이다

 

만약 System, String 관련 .class 파일이 로딩되지 않았으면

Hello.class 파일을 로딩하지 못한다

 

2) 런타임 동적 로딩

코드를 실행하는 순간에 필요한 클래스를 로딩하는 것

 

쉽게말해 JVM이 실제로 .class 파일을 실행할 때

코드 속에서 이러이러한 .class을 로딩하라는 코드를 발견하고

그 순간 .class 파일을 로딩하는것을 말한다

 

우리가 알고싶은 Class.forName("로드할 클래스 이름");

이것이 런타임 동적 로딩에 해당한다고 볼 수 있다

 

 

위에서 Javac.exe 가 .class 파일을 만드는것이고

Java.exe로 JVM이 실행될 때 런타임 동적 로딩이 된다

 

3. 사용 예시

자바에서 DB를 연결할때 아래와 같이 작성한다

 

	try{
		Class.forName("oracle.jdbc.driver.OracleDriver"); 
	}catch (ClassNotFoundException e){
		//에러처리하는 코드 
	}
	Connection conn=null;
	Statement stmt=null;
	ResultSet rs=null;
	
	try{
		conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:xe","jsp","oracle");
		stmt=conn.createStatement(); //쿼리 수행
		rs=stmt.executeQuery("SELECT 1 FROM DUAL");
		if(rs.next())  System.out.print(rs.getInt(1));
		
	}catch (SQLException e){
		//에러처리하는 코드 
	}finally {
		if(rs!=null){try{rs.close();} catch(Exception e){} }
		if(stmt!=null){try{stmt.close();} catch(Exception e){} }
		if(conn!=null){try{conn.close();} catch(Exception e){} }
	}

 

여기서 맨 위에 Class.ForName 을 확인해 보면

"oracle.jdbc.driver.OracleDriver" 라고 적혀있다

이는 JVM 실행하다 "oracle.jdbc.driver.OracleDriver" 만나면

OracleDriver 로드하고 실행해 라는 의미가 된다

 

여기서 의문은 oracle 드라이버는 실행도중 로드가 되었다

그런데 로드만 했지 변수 선언하고 드라이버 객체를 받지도 않았는데

어떻게 밑에서 conn = DriverManager.getConnerction을 쓸 수 있을까?

 

이유는

Driver 클래스의 static{ } 구문이 있기 때문이다

(OracleDriver는 Driver에 자식이기에 부모의 것을 쓴다)

 

Driver의 static 구문

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
           java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    
    그외 기타 기능
}

 

OracleDriver의 static 구문

static 
    {
        defaultDriver = null;
        Timestamp timestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
        try
        {
            if(defaultDriver == null)
            {
                defaultDriver = new OracleDriver();
                DriverManager.registerDriver(defaultDriver);
            }
        }
        catch(RuntimeException runtimeexception) { }
        catch(SQLException sqlexception) { }
    }

 

정리하자면

1) Class.forName()을 통해 실행도중에 오라클 드라이버를 로드한다

2) 로드되면 OracleDriver의 staitc{ } 구문 을 통해

    DriverManager에 OracleDriver를 등록한다

3) DriverManager.getConnection()을 통해 Oracle에 연결한다

4) 이후에 쿼리를 수행한다

 

4. 최종 사용이유 정리

1) Driver의 경우 로드만 하면 되는거지 객체를 생성해서

메모리를 낭비할 필요가 없기 때문에

OracleDriver oracleDriver=new OracleDriver(); 을 통해

객체를 굳이 생성해서 쓰지 않고

Class.forName() 을 이용해서 사용한다

 

2) 환경에따라 원하는 Driver를 로드할 수 있어서

즉 모든 Driver 로드할 필요없어서