참고:

https://www.quora.com/What-are-command-line-arguments-1


 

Java를 처음 사용하기 시작했다면 

이런 에러를 종종 볼 수 있다.

 

 

 

원인은 여러가지가 있다.

1. main메소드를 선언하지 않았을 때

자바 프로그램이 실행되면 가장 먼저 하는 일이 main 메소드를 찾는 것이기 때문에,

이 에러가 발생하면 어떤 수행도 진행되지 않는다. 

 

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 메소드를 실행하게 된다. 

그러니 실행 전엔 항상 저장을 하는 습관을 들이자!

 

참고자료

인프런 자바 프로그래밍 입문 강좌 ,

오라클 Java Language Specification ,

https://docs.oracle.com/javase/specs/jvms/se12/html/jvms-2.html

그 외 블로그..

https://minwan1.github.io/2018/06/06/2018-06-06-Java,JVM/

https://sehun-kim.github.io/sehun/JVM/


 

객체지향프로그래밍(Object Oriented Programing)

객체끼리 상호작용하는 프로그래밍 방법. JAVA, C++...

 

객체(Object)

포괄적 의미: 속성을 가진 모든 것. 사람(키,혈액형,이름 등의 속성이 있음),과자(당도,모양 등의 속성이 있음)

프로그램 관점: 객체를 데이터화 해서 실제 메모리에 올린 것

 

클래스(Class)

객체를 어떻게 데이터화 시킬건지 정의하는 설계도

속성 정의(어떤 값을 가짐), 메소드 정의(어떤 동작을 수행)

 

->즉, 객체지향프로그래밍은 

클래스에서 객체를 뽑아내서 그 객체들을 이용해서 어떤 동작을 수행하는 프로그램을 만드는 것이다.

Car라는 클래스에서 포르쉐,아우디,벤츠라는 객체가 만들어지면 3대의 자동차가 레이싱을 하는 프로그램을 만들 수 있다.

 

->장

클래스와 패키지로 구분되기 때문에 잘 만들어진 설계도를 가져와서

내가 원하는 기능을 추가해서 쓸 수 있다. 혹은 설계도를 나눠서 만들 수 있어서 협업이 편하다.

더보기

내 경험:

->단

설계도를 재사용을 하기 때문에 설계시 많은 고민이 필요하다.

객체를 많이 만들면 처리하는 속도가 느려진다.

더보기

내 경험:


JAVA 동작 과정

 

 

"개발자"가 자바 코드를 작성하고 코드 파일을 저장한다. 이때, 자바 코드 파일의 확장자는 .java이다.

"자바 컴파일러"는 .java파일을 .class파일로 만든다. (이 시기를 컴파일 타임이라고 한다)

더보기

클래스 파일로 만든다는 것은 바이트 코드로 만든다는 것이다.

바이트 코드란? JVM이 읽을 수 있는 코드를 뜻한다. cpu가 0110101과 같은 이진코드를 읽을 수 있듯이 cpu역할을 하는 jvm은 아래와 같이 생긴 바이트 코드를 읽을 수 있다.

jvm이 바이트코드를 읽는 것은 자바의 독립성과 관련이 있다. 이 페이지 하단에서 설명할 것!

"jvm"은 .class파일을 읽어서 코드가 나타내는 동작을 수행한다. (이 시기를 런타임이라고 한다)

 

이때, JVM이 동작하기 위해선 JRE가 있어야하고 JRE는 JDK에 포함되어 있다.

이게 무슨 말이냐?? 꽤 중요한 부분이니 집중하자!!

 

 

JVM(Java Virtual Machine):

자바가상머신, cpu칩과 같은 역할을 하는 소프트웨어 칩이다. cpu칩이 기계어 코드를 읽는다면 JVM은 바이트 코드를 읽는다. 클래스 파일을 실행시킬 때 동작하기 때문에 런타임의 엔진에 속한다.

JAVA와 OS사이에서 바이트 코드를 기계어로 변환시켜준다. 

이 말은 즉, JAVA는 이식성이 좋다는 것을 의미한다. 

어떤 OS에서 한번 클래스파일을 만들고 나면, 다른 OS에서 별다른 수정없이

클래스파일을 실행시켰을 때 동일한 결과가 나오기 때문이다.

 그래서 JAVA는 OS에 독립적이고, JVM은 종속적이라고 할 수 있다.

또 JVM에 포함되는 GC(가비지 컬렉터)는 힙의 메모리를 알아서 관리해준다.

C언어 같은 경우 메모리를 할당한 뒤 사용이 끝나면 직접 해제를 해줘야 하는데

JAVA는 GC가 존재하기 때문에 메모리를 효율적으로 관리할 수 있다.

그래서 JAVA와 C의 가장 큰 차이를 꼽는다면, JVM의 유무라고 할 수 있다.

 

JRE(Java Runtime Environment):

JVM과 JVM이 동작할때 필요로 하는 파일들을 포함한다. 이름 그대로 컴파일타임이 아닌

런타임의 환경이므로 소스파일이 아닌 클래스파일일때 작동한다.

 

JDK(Java Development Kit):

JRE와 javac.exe 등을 포함한다.

자바로 프로그램을 개발하는데 필요한 것을 모아둔 키트이다. 

소스파일에서 클래스파일이 되기까지의 과정을 가능하게 해주므로

컴파일타임을 위해서 javac(자바컴파일러)를 포함하는 것에 주의하자.

 

 

모두 Oracle사이트에서 다운로드 받을 수 있다.

+여담이지만, 자바를 제임스 고슬링이 썬이란 기업에서 발명했고 썬은 오라클에 인수되어

현재 오라클이 자바 업데이트를 관리하고 있다. 일반적으로 java로 개발을 하려면 jdk를 설치하면 된다.

현재 jdk최신 버전은 12이며 8이 가장 안정화되어 있다.

목적에 따라 SE(개인용),EE(기업용),ME(임베디드용)로 나뉘어져 있는데 처음 시작한다면 SE를 설치하면 된다.

 

+필요에 따라 jdk를 설치하지 않을수도 있다.

가령, 이클립스 툴을 통해 Java 어플리케이션을 개발한다면 jdk가 필요하다.

하지만, Tomcat 웹서버를 구동하기 위해서는 jre만 필요하다.

Tomcat은 사용자 입장에서 Class 파일만 구동시킬 수 있으면 그만이기 때문이다.


cmd에서 메모장으로 자바 코딩

*파란색 글씨는 입력해야하는 명령어입니다*

*jvm이 설치되어 있고 환경변수까지 설정되어 있어야 합니다*

 

 

0. cmd창에서 파일을 저장할 위치로 이동한다. (cd+ 해당 위치)

더보기

정말정말 초보를 위해서.. 위치를 알아내는 법! 동그라미 친 부분을 클릭하면 경로 복사가 가능하다

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이 생긴다.
  • 메소드를 실행
  • ”}”괄호를 만나게 되면 Stack Frame이 사라진다.
  • JRE는 JVM을 종료시키고 위치했던 메모리들이 모두 없어진다.

 

 

 

 

 

Execution Engine

Runtime Data Areas에 배치된 바이트코드를 명령어 단위로 읽어서 실행한다.

그 방식은 Interpreter, JIT 두 가지가 있다.(다른 포스팅) 

 

 

 

 

+ Recent posts