[자바 문법] 애플리케이션 실행 방법

  • 2020-07-14 일자 수업 내용
  • eomcs/eomcs-java src/main/com/eomcs/lang/ex01~ex02
  • 자바의 정석 Chap1

애플리케이션 실행 방법

프로그램 언어 해석 / 실행 방법

compile

프로그래밍 언어를 Runtime 이전에 기계어로 해석하는 작업 방식이다. 런타임 이전에 Assebly 언어로 변환하기 때문에 구동시간이 오래 걸리지만, 구동된 이후에는 하나의 패키지로서 매우 빠르게 작동된다.

런타임 이전에 이미 해석을 마치고 대체 컴파일 결과물이 바로 기계어로 전환되기 때문에 OS 및 빌드 환경에 종속적이다. 그러므로 OS 환경에 맞게 호환되는 라이브러리와 빌드 환경을 구분해서 구축해야 한다.

Compile 언어에는 대표적으로 C/C++, Java 등이 있다.

인터프릿(interpret)

런타임 이전에 기계어로 프로그래밍 언어를 변환하는 컴파일 방식과 다르게, 런타임 이후에 Row 단위로 해석하며 프로그램을 구동시키는 방식이다.

프로그래밍 언어를 기계어로 바로 바꾸지 않고 중간 단계를 거친 뒤, 런타임에 즉시 해석하기 때문에 바로 컴팩트한 패키지 형태로 Binary 파일을 뽑아낼 수 있는 Compile 방식에 비해 낮은 퍼포먼스를 보인다. 대신 런타임에 실시간 Debugging 및 코드 수정이 가능하다.

메모리를 별도로 할당받아 수행되지 않으며 필요할 때 할당하여 사용한다. 코드의 흐름 자체도 실제 필요할 때, 실제 수행되어야하는 시점에 수행하기 떄문에 덕 타이핑이 가능하지만, 정적 분석이 안된다는 단점을 갖는다.

출처: https://jins-dev.tistory.com/entry/Compiler-%EC%99%80-Interpreter-%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%B0%A8%EC%9D%B4%EC%A0%90

덕 타이핑(Duck Typing)

덕 타이핑(duck typing)은 동적 타이핑의 한 종류로, 객체의 변수 및 메소드의 집합이 객체의 타입을 결정하는 것을 말한다. 클래스 상속이나 인터페이스 구현으로 타입을 구분하는 대신, 덕 타이핑은 객체가 어떤 타입에 걸맞은 변수와 메소드를 지니면 객체를 해당 타입에 속하는 것으로 간주한다.

만약 어떤 새가 오리처럼 걷고, 헤엄치고, 꽥꽥거리는 소리를 낸다면 나는 그 새를 오리라고 부를 것이다.

출처: https://ko.wikipedia.org/wiki/%EB%8D%95_%ED%83%80%EC%9D%B4%ED%95%91#:~:text=%EC%BB%B4%ED%93%A8%ED%84%B0%20%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%20%EB%B6%84%EC%95%BC%EC%97%90%EC%84%9C%20%EB%8D%95,%EC%9D%84%20%EA%B2%B0%EC%A0%95%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9D%84%20%EB%A7%90%ED%95%9C%EB%8B%A4.

정적 프로그램 분석

정적 프로그램 분석의 핵심은 프로그램을 실행하지 않은 채 소스 코드만으로 우리가 찾고 싶은 어떤 성질을 검증하는 것이다. 이러한 성질의 예는 다음과 같다.

  • 프로그램 각 지점에서 각 변수가 갖는 정수 값의 범위
  • 어떤 변수가 참조됐을 때 그 변수가 갖는 값이 널인지 아닌지의 여부
  • 시스템 콜에 전달되는 인자 값이 외부에서 입력된 위험한 값인지의 여부

대표적인 Interpreter 언어로 Javascript와 같은 스크립팅 언어가 있고, 스크립트 언어뿐만 아니라, 컴파일 이후의 동작에서 Interpret을 수행하는 언어도 존재한다.

많은 프로그래밍 언어들의 인터프리터는 해석을 위한 Virtual Machine을 두고, Machine 위에서 Interpret을 수행하게 되는데, 이 때 해석의 기반이 되는 머신들이 OS 환경들을 지원해줌으로써 해당 방식으로 인터프리터는 OS 및 플랫폼에 종속되지 않는 프로그램 구동이 가능하게 된다. 이런 특징을 지닌 Interpreter는 Java의 JVM과 Phthon의 Anaylzer가 있다. (자바는 컴파일러가 소스코드를 컴파일해서 바이트 코드로 만든 후, 런타임에서 이 바이트 코드를 인터프리터가 해석하는 방식을 취하고 있다.)


JVM(Java Virtual Machine)

JVM은 자바를 실행하기 위한 가상 기계(컴퓨터)라고 할 수 있다. 가상 기계는 소프트웨어로 구현된 하드웨어를 뜻하는 넓은 의미의 용어이다. 자바 애플리케이션이 실행되기 위해서는 반드시 JVM이 필요하다. 일반 애플리케이션의 코드는 OS만 거치고 하드웨어로 전달되지만, 자바 애플리케이션은 OS로 가기 전에 JVM을 거친다.

소스 코드는 하드웨어에 맞게 컴파일된 상태가 아니고, 실행 시에 해석(interpret)되기 때문에 속도가 느리다는 단점을 갖는다. 요즘에는 바이트 코드를 기계어로 바로 변환하는 JIT 컴파일러와 향상된 최적화 기술이 적용되어서 속도의 격차를 많이 줄였다.

위에서 설명했듯이 JVM은 실행 시 OS에 맞는 기계어로 변환하기 위해서 OS 종속적이다. 따라서 OS가 아닌 JVM하고만 상호작용하는 자바 어플리케이션은 OS와 하드웨어에 대해 독립적일 수가 있다.


자바 실행 방법

JDK의 bin 디렉토리에 있는 주요 실행 파일들은 다음과 같다.

  • javac.exe 자바 컴파일러, 자바 소스 코드를 바이트 코드로 컴파일한다.
  • java.exe 자바 인터프리터, 컴파일러가 생성한 바이트 코드를 해석하고 실행한다.
  • javap.exe 역어셈블러, 컴파일된 클래스 파일을 원래의 소스로 변환한다.
  • javadoc.exe 자동문서생성기, 소스 파일에 있는 주석을 이용하여 Java API문서와 같은 형식의 문서를 자동으로 생성한다.
  • jar.exe 압축 프로그램, 클래스 파일과 프로그램의 실행에 관련된 파일을 하나의 jar 파일로 압축하거나 압축 해제한다.

자바로 프로그램을 개발하기 위해서는 다음과 같은 과정을 거쳐야 한다.

  1. 텍스트 편집기로 소스 파일(.java)을 작성한다.
  2. 자바 컴파일러(javac.exe)를 사용해서 소스 파일(.java)로부터 클래스 파일(.class)을 생성한다.
  3. 이 클래스 파일을 자바 인터프리터(java.exe)로 실행한다.
$ javac Hello.java

$ java Hello
Hello, world

컴파일

컴파일 명령어

$ javac -d bin/main -encoding UTF-8 src/main/java/com/eomcs/basic/ex01/Exam1_1.java
  • -d 컴파일된 클래스 파일을 위치시킬 파일 경로
  • -encoding 자바에서 사용하는 인코딩 정보를 직접 설정해주는 옵션이며, 옵션을 주지 않을 경우 OS에서 설정된 기본 인코딩을 따르게 된다.

클래스 블록

자바 컴파일러는 클래스 블록 단위로 컴파일을 수행하여 클래스 파일을 생성한다.

class A {}
class B {}
class C {} 

위처럼 작성된 자바 파일 한개를 컴파일하면 -d 옵션으로 지정된 파일 경로에 A.class, B.class, C.class, 이렇게 세 개의 클래스 파일이 생성된다.

클래스 이름과 소스 파일 이름

공개 클래스의 경우 소스 파일명이 클래스 이름과 같아야 하며 다르면 컴파일 오류가 발생한다. 비공개 클래스의 이름은 소스 파일명과 일치할 필요는 없다. 여기서 공개 클래스란 접근 제어자가 public으로 설정된 클래스를 말한다. 대부분은 공개 여부와 상관없이 한 소스 파일에는 한 클래스만을 작성한다. 이렇게 클래스명과 소스 파일명을 같게 하면 유지보수할 때 클래스를 찾기 용이하다.

소스 파일의 인코딩 지정하기

컴파일할 떄 소스 파일의 인코딩 문자집합을 지정하지 않으면 OS의 기본 인코딩으로 저장되어있다고 간주하고 컴파일한다. 따라서 OS와 다른 기본 인코딩과 다른 문자집합이라면 옵션을 지정해줘야만한다.

class Exam0300 {
  public static void main(String[] args) {
    System.out.println("안녕하세요!");
  }
}

이 소스 파일은 UTF-8 문자집합으로 저장되어있는데, 그와 다른 인코딩으로 설정하여 컴파일할 경우에는 다음과 같이 에러가 뜬다.

$ src/main/java/com/eomcs/lang/ex01/Exam0300.java
src/main/java/com/eomcs/lang/ex01/Exam0300.java:3: error: unmappable character (0xEC86) for encoding CP949

실행

실행 명령어

$ java -cp bin/main com.eomcs.basic.ex01.Exam4
  • -cp 실행 클래스 파일이 있는 파일 경로를 직접 지정해주는 옵션이다. 이 옵션을 생략하면, 명령어를 실행시키는 위치에서 클래스 파일을 찾는다.

main 메서드

JVM을 통해 클래스를 실행하면, JVM은 그 클래스에서 main 메서드를 찾아 한줄씩 실행한다.

콘솔에서 위와 같이 Java 애플리케이션을 실행시켰을 내부적인 진행 순서는 다음과 같다.

  1. 실행할 클래스 파일을 CLASSPATH에 등록된 디렉토리 경로에서 찾는다.
  2. 클래스 파일의 유효성을 검사한다.(파일 형식, 악성코드 체크)
  3. 메모리에 바이트 코드를 적재(load)한다.
  4. 지정된 클래스(Hello)에서 main 메서드를 찾아 실행한다.

main 메서드의 첫 줄부터 코드가 실행되기 시작하여 마지막 코드까지 모두 실행되면 프로그램이 종료되고, 프로그램에서 사용했던 자원들은 모두 반환된다.


주석

코드에 대한 이해를 돕기 위해 붙이는 설명이며 컴파일될 때 무시되므로 클래스 파일에 존재하지 않는다.

여러 줄 주석(traditonal comment)

주석의 끝 표시를 만날 때까지 주석으로 간주되므로 여러 줄의 설명을 붙일때 유용하다.

/*
여
러
줄
주
석
*/

한 줄 주석(end-of-line comment)

줄이 끝날 때까지 주석으로 간주한다.

// 한 줄 주석

Javadoc 주석

java document comment(doc comment)의 약자로 javadoc에서 HTML 문서를 만들 때 사용하는 주석이다. 주로 API 문서를 자동 생성할 때 사용한다. 클래스나 메서드, 변수 선언에 붙일 수 있다.

/**
* @author eomjinyoung
*
*
*/
public class Exam0200 {
  /**
  * 변수에 대한 설명
  * 변수 선언 앞에 설명을 붙여 놓으면 나중에 HTML 문서를 만들 때 추출할 수 있다.
  */
  public static String message = "Hello, world!";
  
  /**
   * 메서드에 대한 설명
   * 메서드에 대한 설명을 여기에 붙여 놓으면 나중에 HTML 문서를 만들 때 추출할 수 있다.
   * @param args 애플리테이션 아규먼트 값을 보관한 배열
   */
  public static void main(String[] args) {
    System.out.println(message);
  }
}

}

위와 같이 자바 파일을 작성하고 Javadoc.exe 도구를 사용하여 자바 소스 파일에서 Javadoc 주석을 추출하여 HTML 파일을 생성할 수가 있다. 다음과 같이 옵션을 주며 직접 파일을 만들어보자.

$ javadoc
    -encoding [소스 파일 인코딩]
    -charset [생성될 HTML 파일의 인코딩 정보]
    -d [생성된 파일을 놓아둘 디렉토리]
    -sourcepath [자바 소스 경로] [자바 패키지]

애노테이션

클래스, 변수(필드, 아규먼트, 로컬 변수), 메서드 선언에 붙이는 주석으로, 컴파일러나 JVM에서도 사용된다. 따라서 컴파일 한 후에도 클래스에 주석을 유지할 수 있으며, JVM이 실행되면 메모리에 클래스가 로딩될 때에도 주석이 함께 로딩될 수 있다.

public class Exam0330 {
  public static void main(String[] args) {
    System.out.println("애노테이션")
  }
  
  @Override
  public String toString() {
    return "Exam12";
  }
}

@Override 애노테이션이 toString 메서드에 붙여지면서 해당 메서드에 오버라이딩 규칙이 적용된다. 이 규칙은 자바 소스가 컴파일될 때부터 적용된다.

Comments