2. public static void main(String[] args)에 오타가 있거나 임의로 수정했을 때.
위의 문장은 하나하나 의미가 있기 때문이다.
public: 가장 먼저 호출해야하므로 접근에 제한이 있으면 안되므로 무조건 public이어야만 가능하다.
생략하는 것도 안된다. 생략하면 접근제어자가 default(같은 패키지에서만 접근 가능)가 적용되기 때문이다.
static: 아까 말했듯이, 어떤 코드보다 가장 먼저 실행되어야 하므로 객체를 만드는 코드 이전에 작동하기 위해선
static을 붙여야한다. 그렇게하면 인스턴스 생성이 되지 않아도 접근이 가능하기 때문이다. static을 붙이면 인스턴스에 속해 있지 않고 클래스 범위로 소속되기 위해 JVM메모리의 method 영역에 정보가 올라간다.
void: main메소드가 가장 먼저 시작했기 때문에 main이 반환한 값을 처리할 메소드는 없기 때문에 반환형은 void이어야만 한다.
main: main이란 키워드로 메소드를 찾기 때문에 그대로 써줘야한다.
String args[]: 나는 처음에 String args[]를 써야하는 이유에 대해 궁금했었다.일단 위치는 매개변수 자리이다. 즉, 이 클래스 파일을 실행할 떄 문자열 배열 정보를 함께 준다는 것이다. 그 말은 즉, 프로그램을 모듈화 할 수 있다는 뜻이다. 예를 들어서, 하나의 메인 메소드가 실행될 때 args에 담긴 문자열이 "삭제"라면 삭제에 관한 함수를 실행시키도록 하는 것이다. 추가로 주는 정보에 따라서 여러 동작을 수행할 수 있도록 모듈화 하는 것이다. 일반적인 메소드에서의 매개변수를 떠올리면 되지만, main의 매개변수는 이런 모듈화 성격이 더 짙다.
커맨드라인(이클립스 IDE가 아닌 cmd창에서 텍스트 기반으로 프로그램을 만드는 경우)에서는 바로 명령어를 args에 넣을 수 있다. 하지만 이클립스 IDE에서는 GUI 기반으로 Run Configurations..->Arguments->Program arguments에서 원하는 명령어를 넣을 수 있다.
처음 JAVA로 프로젝트를 할 때, 오픈소스를 사용하는데 입력 받는 함수가 없을 때 인풋(입력값)을 어디에 넣어야 하는지 헤맨 적이 있었다. 그때 찾은 간단히 해결하는 방법이 이것이다.
3. 수정된 파일을 저장하지 않고 컴파일 했을 때
초보일 때 이 에러의 가장 많은 원인이라고 생각한다. 나도 아직 초보이긴 하지만.. 프로젝트를 할 때 종종 main을 찾을 수 없다고도 나오고, 이전에 작성한 코드의 결과값이 출력되는 경우가 더러 있었다.
당시에 검색을 했을 때는 이클립스에서의 에러보단 콘솔에서의 코드 오탈자로 설명하는 글이 많았다. 콘솔에서 main을 찾을 수 없는 문제는 대부분 .java 파일을 컴파일 할 때 확장자까지 모두 써줬던 것처럼 .class파일 또한 끝까지 다 쓴 경우 생기는 에러였다. (클래스파일은 실행만 바로 하면 되는 .exe 프로그램이기 때문에 이름만 써주면 된다!)
하지만 이클립스에서는 코드를 저장하지 않아서 생기는 문제이다. 정확히는, 컴파일을 하지 않고 run을 해서 생기는 문제이다. 이클립스에서 컴파일은 단축키가 ctrl+s이다. main을 작성하지 않고 저장한 상태에서 main을 작성하고 곧바로 run을 하면 에러가 발생한다.
여기서 ctrl+s로 저장 및 컴파일을 하고나서 실행을 하면 잘 실행이 된다.
만약 main을 찾을 수 없는 상황이더라도, 같은 프로젝트에서 main이 존재하는 클래스가 있다면 에러 메시지를 출력하지 않고 그 클래스의 main 메소드를 실행하게 된다.
정말정말 초보를 위해서.. 위치를 알아내는 법! 동그라미 친 부분을 클릭하면 경로 복사가 가능하다
C:\~~에 뭐가 더 붙었을 것이다..현재 위치가 바뀌었다는 말! 이젠 메모장 실행 (notepad)
1. 메모장에서 프로그램이 수행할 동작을 JAVA 문법을 사용한 코드로 작성하고
파일 이름은 Test.java로 저장한다 (클래스이름+확장자 .java)
2. 지금 위치에 코드 파일이 잘 저장되었는지 확인 (dir)
3.자바 컴파일러를 불러와서 컴파일 해준다. (javac + java파일이름.java)
4. 2번과 마찬가지로 확인해보면 기존의 java파일과 새로 생성된 class파일이 있다.
5.class파일을 jvm으로 실행시킨다. (java + class파일이름)
!!주의할 점!!
4번에선 파라미터의 이름이 Test.java이지만 5번에선 Test이다.
5번에서 확장자를 적으면 에러가 발생한다.
이유는 나의 추측이지만,class파일로 만들면서 이미 문법의 유효성이나 확장자로 파일 내용의 유효성 검사를 마쳤고,
실행만 하면 되기 때문 아닐까싶다.
이 모든 과정을 우리는 시꺼먼 cmd 대신 이클립스라는 보편적이고 깔끔한 IDE로 진행할 수 있다.
IDE에서 코드를 작성하면 javac와 같은 명령어는 입력하지 않아도 된다.
ctrl+s가 javac역할을 하고
run버튼이 java역할을 하기 때문이다.
JVM 동작 과정
위 그림의 큰 사각형에 포함되는 부분을JVM 아키텍처라고 부른다.
JVM은 Class Loader,Runtime Data Areas,Execution으로 구성된다.
1. 컴파일러가 소스코드를 컴파일해서 클래스파일로 만들고 난 뒤, 클래스파일을 실행한다.
-JVM 동작 시작-
2. 클래스로더가 바이트코드를 Runtime Data Area에 로딩한다.
3.4.3.4..바이트코드는 Execution 엔진에 의해 해석된 후 해석된 코드는 Runtime Data Areas의 각 영역의 목적에 맞게 배치되며 실질적인 수행이 이루어진다.
Runtime Data Areas
프로그램이 실행될 때 JVM이 운영체제로부터 할당받는 메모리 영역이다.
생성 시기에 따라 분류하면 다음과 같다.
1.쓰레드가 시작될 때마다 생성(쓰레드마다 할당받는 메모리)
PC Resiter
여러 쓰레드들은 자신이 현재 실행중인 메소드의 주소를 저장하고 있다.
JVM Stack(
스택프레임(메소드 단위)으로 push(메소드 시작) pop(메소드 종료) 연산을 수행한다.
각 '스택프레임'은 'Local Variable Array 지역변수배열'와 'Operand Stack 피연산자 스택'의 참조값을 저장한다. 이 값들은 컴파일시에 크기가 결정 되었으므로 JVM스택의 크기는 쓰레드가 실행되는 초기에 고정된다. 그러므로 이 크기를 넘는 경우 Stack Overflow가 발생할 수 있다.
이 과정에서 JVM스택은 힙과 함께 동작한다.
Local Variable Array:
0은 this 주소
1부터 매개변수
그 뒤는 지역변수
Operand Stack:
메소드의 실제 작업공간. Local Variable Array와 데이터를 교환한다. 다른 메서드 호출 결과를 push pop한다.
Native Method Stack
C/C++ 코드를 수행하기 위한 스택이다.
2.모든 쓰레드가 공유
Method Area,Runtime Constatnt Pool
JVM이 시작될 때 각 클래스의 구조를 텍스트(바이트코드)로 저장하는 영역이다.(컴파일때 크기가 정해져서 크기 고정)
Rutime Constant Pool,필드 코드, 메소드 코드를 포함한다.
특히 Runtime Constant Pool에선 모든 메서드,인터페이스의 실제 주소를 가지고 있다.
이 영역에 있는 클래스 정보로 Heap 영역에 객체를 생성한다.
Heap
런타임에 할당되는 영역이며, 모든 클래스와 배열의 객체가 저장되는 곳이다. GC(따로 포스팅) 의 대상이며 동기화 처리가 일어나는 영역이다. GC에 의해 자동적으로 버릴 메모리를 관리하며 정해진 힙의 크기를 넘어가면 OutOfMemoryError가 발생한다.
JRE가 자바프로그램을 실행시킬 때 맨처음으로 main()를 찾는다.
있으면 Class Loader가 목적파일(.class)을 실행시킴
static 영역에 java.lang 패키지, import한 패키지들을 위치시킨다. 프로그램에 있는 모든 클래스와 필드 ,메소드가 올라감
stack영역에 main()의 Stack Frame이 위치하고 변수 영역에 인자를 위치시킨다.
지역변수의 경우 선언이 아닌 초기화 될 때 위치된다.
클래스 선언 {}을 제외하고 메소드의 {}, if의 {}이 생길때 마다 Stack Frame이 생긴다.