public class Outer {
class Inner {
void display() {
System.out.println("Inner class");
}
}
}
public class Outer {
static class Inner {
void display() {
System.out.println("Static Inner class");
}
}
}



"Hello" 는 Heap 영역 내에 String Pool에 저장되어 재사용됨.new String("Hello") 는 같은 내용이라도 여러 개의 객체가 각각 생성되어 Heap 영역을 차지하게 됨. public class StringExample {
public static void main(String[] args) {
String str1 = "Hello"; // String 리터럴
String str2 = "Hello"; // String Pool에서 동일한 객체를 참조
String str3 = new String("Hello"); // 새로운 String 객체 생성
String str4 = new String("Hello"); // 또 다른 새로운 String 객체 생성
// str1과 str2는 동일한 객체를 참조
System.out.println(str1 == str2); // true
// str3과 str4는 서로 다른 객체를 참조
System.out.println(str3 == str4); // false
// 문자열 값은 동일함
System.out.println(str3.equals(str4)); // true
}
}
.java 파일을 .class 파일로 변환하는 과정.jar .war 파일 생성빌드 관리 도구
Maven 은 pom.xml 파일을 통해 프로젝트 설정 및 의존성 관리를 진행.
Gradle 은 build.gradle 파일을 통해 프로젝트 설정 및 의존성 관리 진행.
차이점 추가 정리 필요
.class.class.class 파일이 생성됨 .jar.java 파일을 .class 라는 자바 바이트 코드로 변환시켜준다. 하지만 바이트 코드는 기계어(Native Code)가 아니므로 OS에서 바로 실행이 되지 않는데, 이 때 JVM은 OS가 Byte Code를 이해할 수 있도록 해석해주는 역할을 한다. 
java 소스코드를 작성하고 java 컴파일러를 통해 컴파일을 하면 .class 파일이 생성이 됨.

java 명령어로 class 파일을 실행하면, JVM은 class loader를 통해 이 클래스를 읽어들임.
클래스 파일 안에는 클래스 안에 어떤 필드가 몇 개 선언 되어있는지, 메서드는 몇 개이고 이름은 무엇인지, 바이트코드까지 포함한 클래스의 모든 정보를 담고 있음.
Class Loader System은 클래스 파일 정보를 Method Area 에 올리고, static 변수 등을 초기화 하는 역할을 함.
Runtime Data Area는 JVM이라는 가상 머신이 사용하는 메모리 공간
바이트코드란 JVM이 알아들을 수 있는 명령어들의 집합을 의미.
JVM의 목적은 바이트 코드를 기계어로 번역해서 CPU에게 일을 시킴.
바이트 코드를 기계어로 번역하는 일을 Interpreter가 실행함.







Symbolic Reference
Class References : 다른 클래스나 인터페이스 참조
Filed References : 클래스 또는 인터페이스의 필드 참조
Method References : 메소드 호출에 사용되는 참조
Interface Method References : 인터페이스 내의 메소드 참조
Name and Type Descriptors : 필드나 메소드의 이름과 그 타입을 저장
리터럴 값 (Literals)
ldc 명령어를 통해 로드됨. Crew 클래스에서 name 필드를 참조하려고 할 때, 컴파일된 코드에서는 Crew.name 이라는 Symbolic Reference를 사용. 클래스가 로드되고 해석(Resolution) 과정을 거쳐 JVM은 Crew 클래스의 실제 메모리 주소과 name 필드의 정확한 위치를 찾아내 Direct Reference 로 변환. public class org.jvminternals.SimpleClass
SourceFile: "SimpleClass.java"
minor version: 0
major version: 51
flags: ACC_PUBLIC, ACC_SUPER
//상수풀!!! 이 부분을 보세요!
Constant pool:
#1 = Methodref #6.#17 // java/lang/Object."<init>":()V
#2 = Fieldref #18.#19 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #20 // "Hello"
#4 = Methodref #21.#22 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #23 // org/jvminternals/SimpleClass
#6 = Class #24 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 LocalVariableTable
#12 = Utf8 this
#13 = Utf8 Lorg/jvminternals/SimpleClass;
#14 = Utf8 sayHello
#15 = Utf8 SourceFile
#16 = Utf8 SimpleClass.java
#17 = NameAndType #7:#8 // "<init>":()V
#18 = Class #25 // java/lang/System
#19 = NameAndType #26:#27 // out:Ljava/io/PrintStream;
#20 = Utf8 Hello
#21 = Class #28 // java/io/PrintStream
#22 = NameAndType #29:#30 // println:(Ljava/lang/String;)V
#23 = Utf8 org/jvminternals/SimpleClass
#24 = Utf8 java/lang/Object
#25 = Utf8 java/lang/System
#26 = Utf8 out
#27 = Utf8 Ljava/io/PrintStream;
#28 = Utf8 java/io/PrintStream
#29 = Utf8 println
#30 = Utf8 (Ljava/lang/String;)V
{
public org.jvminternals.SimpleClass();
Signature: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lorg/jvminternals/SimpleClass;
public void sayHello();
Signature: ()V
flags: ACC_PUBLIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String "Hello"
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 6: 0
line 7: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lorg/jvminternals/SimpleClass;
}
위의 경우에는 Constant Pool 의 인덱스를 통해 참조. (Symbolic Referece 임)
예를 들어 5: invokevirtual #4 명령어는 Constant Pool에서
#4 = Methodref #21.#22
↓ // Class.NameAndType →
#21 = Class #28 // java/io/PrintStream
#22 = NameAndType #29:#30 // println:
↓ // java/io/PrintStream 클래스의 println 메서드에서 파라미터로 받은 String 출력, 그리고 Void.
#28 = Utf8 java/io/PrintStream
#29 = Utf8 println
#30 = Utf8 (Ljava/lang/String;)V
// PrintStream.println(String)
#4의 Symbolic Reference는 참조하고 참조하고 참조하다가 Method를 실행하기 위한 println 메서드의 실제 실행 코드 주소로 변환됨.