Java

최근 수정 시각:

파일:나무위키+유도.png   동음이의어에 대해서는 자바 문서를 참조하십시오.

파일:나무위키프로젝트.png
이 문서는 나무위키 프로그래밍 프로젝트에서 다루는 문서입니다.
해당 프로젝트 문서를 방문하여 도움이 필요한 문서에 기여하여 주세요!

package wiki.namu;

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, world!");
    }
}

TIOBE에서 선정한 프로그래밍 언어 월간 점유율 순위 (2018년 1월 기준)

1. Java

2. C

3. C++

4. Python

5. C#

14.215%
3.06% 감소

11.037%
1.69% 증가

5.603%
0.70% 감소

4.678%
1.21% 증가

3.754%
0.29% 감소

전년 동월 대비 변화 수치이다. 자세한 내용은 이곳에서 확인할 수 있으며, 기준은 다음과 같다.



파일:java 로고.png

1. 개요2. 어원3. 분류4. 간략한 역사
4.1. JDK 1.0a4.2. JDK 1.0a24.3. JDK 1.04.4. JDK 1.14.5. J2SE 1.24.6. J2SE 1.34.7. J2SE 1.44.8. J2SE 54.9. Java SE 64.10. Java SE 74.11. Java SE 84.12. Java SE 9
5. C, C++와의 비교6. 특징
6.1. 장점
6.1.1. 수많은 개발자와 레퍼런스6.1.2. 비교적 높은 생산성6.1.3. 기기 호환성6.1.4. 안정성6.1.5. 소스 코드 가독성
6.2. 단점
6.2.1. 속도 문제
6.2.1.1. JVM 로딩 속도문제6.2.1.2. 가상 머신 바이트코드 실행 속도 문제6.2.1.3. 가비지 컬렉션에 의한 실행 지연문제
6.2.2. 불편한 예외 처리6.2.3. 소스 코드 길이6.2.4. 언어적 불편함
6.2.4.1. 명사형 생각을 강제6.2.4.2. 클로저 미지원
7. 개발환경, JVM 언어
7.1. 개발환경7.2. JVM 언어
7.2.1. 유명한 JVM 언어 목록
7.3. 유사품에 주의합시다
8. 불투명한 미래?9. 여담10. 관련 문서

1. 개요[편집]

썬 마이크로시스템즈에서 1995년에 개발한[1] 객체 지향 프로그래밍 언어. 2010년에 썬이 오라클에 인수되어서 현재 저작권자는 오라클이다. 단, 2017년 9월부로 Java EE에 한해 이클립스 재단이 소유권을 가지게 되었다.

2. 어원[편집]

처음엔 고슬링 사무실 앞에 있는 나무인 OAK로 지었다가 그대로 등록하기엔 상표권에 문제가 생겨서 컨설턴트가 극단적인 방법을 도입, 오후에 개발진들을 회의실에 가둬서(...) 마라톤 회의를 시켰고, "기분이 어떤가요" (Excited!) "무엇이 당신 기분을 좋게 만드나요?" (Java!)같은 연상적인 작용을 거쳐 여러가지 이름을 정하고, 그 중에서 선택했다. Java는 랭킹 중 네 번째. 리스트의 첫 번째 이름은 Silk였고 고슬링이 가장 좋아했던 이름은 Lyrics, 세 번째에 올라왔던 이름이라고.

개발진이 자바산 커피를 좋아해서 그랬다는 설도 있다. 아이콘도 커피잔 모양. 또는 개발자의 이름인 James Gosling, Arthur Van Hoff, Andy Bechtolsheim의 머릿글자를 따온 것이라는 설도 있고, 그냥 사전을 펼쳤는데 눈에 들어온 이름이었다는 설도 있다. 그런데 막 지은 것 치고는 나중에 Sun사의 주식시장 등록 이름이 JAVA가 되어버릴 정도로 이제는 Sun의 상징이자, 세계적으로도 널리 알려진 단어가 되었다. 출처

3. 분류[편집]

자바는 크게 다음과 같은 4가지 에디션으로 나뉜다.

  • Java SE(Standard Edition)
    대부분의 사람들이 가장 많이 접하는 표준 자바 에디션. 자바의 핵심 API와 기능들을 제공한다. JDK 항목도 참고.

  • Java EE(Enterprise Edition)
    Enterprise라는 이름에서 알 수 있듯이 기업에서 운영하는 서버에 특화된 에디션이다. JSP데이터베이스를 비롯한 웹 프로그래밍 관련 기술들이 포함되어 있다.

  • Java ME(Micro Edition)
    PDA나 셋톱박스, 센서 등의 임베디드 환경에 특화된 에디션이다.

  • Java FX
    데스크톱 어플리케이션 개발 및 배포를 위한 에디션으로, 크로스플랫폼 이식과 GUI 라이브러리를 제공한다.

4. 간략한 역사[편집]

4.1. JDK 1.0a[편집]

1994년 발표.

4.2. JDK 1.0a2[편집]

1995년 5월 23일 발표. 언어 자체가 정식으로 발표된 날이기도 하다.

4.3. JDK 1.0[편집]

1996년 1월 23일 발표. 발표 이전에 불렸던 이름은 Oak였으며, 안정화 작업을 거친 1.0.2 버젼에서 Java로 이름이 바뀌었다.

4.4. JDK 1.1[편집]

1997년 2월 19일 발표. 이너 클래스, 자바빈즈, RMI, 리플렉션, 유니코드 지원, 국제화[2] 등이 추가되었다.

4.5. J2SE 1.2[편집]

1998년 12월 8일 발표. 2003년 11월에 일반지원이 종료되었다. 새로운 GUI, JIT, CORBA 등의 굵직한 기능이 추가되면서 2 부터 약칭을 J2SE(Java 2 Standard Edition) 로 표기하기 시작했으며, 이 표기는 5 까지 사용된다. strictfp, SWING GUI, JIT, 자바 애플릿을 구동하는 웹 브라우저 플러그인, CORBA, Collections 등이 추가되었다. 1999년에 업데이트를 통해 HotSpot JVM 이 첫 선을 보인다.

4.6. J2SE 1.3[편집]

2000년 3월 8일 발표. 일반지원은 2006년 11월에 종료되었다. HotSpot JVM, JNDI, JPDA, JavaSound 등이 추가되었다. RMI가 CORBA를 지원하도록 변경되었다.

4.7. J2SE 1.4[편집]

2002년 2월 6일 발표. 일반지원은 2008년 10월, 유료지원은 2013년 2월에 종료되었다. assert, Regular Expression, IPv6, Non-Blocking IO, XML API, JCE, JSSE, JAAS, Java Web Start 등이 추가되었다.

4.8. J2SE 5[편집]

2004년 9월 30일 발표. 일반지원은 2009년 9월, 유료지원은 2015년 5월에 종료되었다. J2SE 5.0 까지 Windows 9x와 Windows NT 4.0이 지원되었다. 이 때부터 버젼 중 앞의 1을 빼버리고 표기하기 시작했다. 그러나 내부적으로는 여전히 1.5, 1.6, 1.7 등으로 데이터가 들어있다. Generics, Annotation, Autoboxing/unboxing, Enumeration, 가변 길이 파라미터, Static Import, 새로운 Concurrency API 등이 추가되었다. Java 는 표준 입력(stdin) 지원이 시원찮았는데, J2SE 5 에 들어서 java.util.Scanner 가 추가되면서 이전보다 편하게 표준 입력을 사용할 수 있게 되었다.

4.9. Java SE 6[편집]

2006년 12월 11일 발표. 일반지원은 2013년 2월 종료되었으며, 유료지원은 2018년 12월에 종료될 예정이다. 이 때부터 표기가 J2SE 에서 Java SE 로 바뀐다. Scripting Language Support, JDBC 4.0, Java Compiler API, Pluggable Annotation 등이 추가되었다. 스크립팅 언어 지원과 함께 Rhino JavaScript 엔진이 기본으로 탑재되었다.

4.10. Java SE 7[편집]

2011년 7월 7일 발표. 일반지원은 2015년 4월에 종료되었으며, 유료지원은 2022년 7월에 종료될 예정이다. Dynamic Language 지원, switch 문에서 String 사용, try 에서 자동 자원 관리, Diamond Operator <>, 이진수 리터럴, 숫자 리터럴에 _ 지원, 새로운 Concurrency API, 새로운 File NIO 라이브러리, Elliptic Curve Cryptography, Java2D 를 위한 XRender, Upstream, Java Deployment Ruleset 등이 추가되었다.

4.11. Java SE 8[편집]

2014년 3월 18일 발표. 일반지원은 2018년 9월, 유료지원은 2025년 3월에 종료될 예정이다. Lambda Expression, Rhino 대신 Nashorn JavaScript 엔진 탑재, Annotation on Java Types, Unsigned Integer 계산, Repeating Annotation, 새로운 날짜와 시간 API(사실상 JodaTime 이라고 보면 된다), Static Link JNI Library, PermGen 영역 삭제, Stream API 등이 추가되었다.

4.12. Java SE 9[편집]

2017년 9월 21일 발표.

Project Jigsaw 기반으로 런타임이 모듈화된 것이 가장 큰 특징. 이에 따라 대부분의 콘솔 프로그램 개발에는 더 이상 AWT나 Swing 같은, 불필요한 라이브러리를 끌어쓸 필요도 없이, 최상위 모듈인 Base만 사용해도 된다. 더불어 특정 프로그램에 최적화된 최소 런타임을 제작할 수 있게 되면서 패키징 역시 간편해졌다.

여기에 자바를 인터프리터 언어 쉘 처럼 사용할 수 있는 JShell이 추가되었으며, Java에서 바로 기계어로 번역하는 선행 컴파일(Ahead-of-time Compile) 기능 역시 시험 기능으로 추가된다.[3] 또한 Deprecated 표시에는 해당 버전과 제거 예정 여부를 표시할 수 있게 된다. 그 외에도 구조적 불변 컬렉션 지원, 통합 로깅 지원, HTTP/2 지원, HTML5 Javadoc 등도 지원되며, 프로퍼티 파일에 UTF-8이 지원됨에 따라 더 이상 인코딩 문제로 삽질할 필요가 없어졌다. 대신 애플릿 기능은 지원이 종료된다.

새로 적용된 버저닝 정책에 따라 이 버전 부터는 더 이상 1.x 버전으로 내놓지 않고, 대신 9.0으로 급속한 판올림이 일어난다. 또한 제거 예정인 Deprecated API는 다음 버전인 Java SE 10부터 완전 삭제 예정이므로 해당 API를 쓰는 프로그램은 더 이상 이후의 버전에서 컴파일 조차 불가능하게 된다.

본래는 2016년 발표 예정이었으나 2번이나 연기되어 2017년 7월 27일 발표 예정, 그나마도 한번 더 연기되어 지금에 이르렀다. 가장 큰 원인은 역시 Project Jigsaw의 개발 난이도. 또한 이 연기 때문에 2017년 9월 종료 예정이었던 Java SE 8 일반 지원이 1년 연장되었다. 게다가 Project Jigsaw의 호환성이 Maven 등 기존 모듈 관리 도구와 그리 좋지 않아 현장에서는 아직 Java 9을 꺼리는 분위기. 실제로 Maven의 Java 9 마이그레이션 작업이 2017년 10월 현재에도 진행 중에 있다. (Apache Maven 공식 진행상황)

5. C, C++와의 비교[편집]

기존의 C에 객체 지향 기능을 억지로 끼워 맞추다 보니 영 모양새가 좋지 않은 C++과는 다르게 아예 처음부터 객체 지향 언어로 개발되었다.[4] C, C++, Java의 차이점을 말하자면, C는 포인터 등을 활용한 로우 레벨 시스템 프로그래밍에 강점을 가지며, C++은 C의 그런 강점을 거의 그대로 가져오면서 거기에 객체 지향과 같은 하이 레벨 기능들을 포함하였다. 문제는, 저수준 메모리 액세스를 허용하면서 하이레벨 기능들을 죄다 포함하려다 보니 디자인적인 측면에서도 좋은 소리를 못 들었고, 실제로 상당히 복잡한 언어가 되어 버렸다. 그래서 C++을 제대로 다룰 줄 아는 프로그래머는 거의 없다는 이야기가 널리 퍼지게 된 것.[5] Java는 여기서 포인터라는 강력한 무기를 포기한 대신에 OOP와 같은 하이 레벨 부분에 보다 집중하여 언어적 완성도를 높였다 볼 수 있다.

일단, 대부분의 프로그래밍 언어가 그렇듯이, C와 비슷한 문법 구조를 가지고 있다. 그리고 명색이 고급 언어이기 때문에 C보다 생산성이 훨씬 더 좋다. 다만, 상속 같은 객체 지향 개념을 이해하지 못하고 헤맬 경우엔 생산성과는 별개로 배우는 데 상당히 힘이 들 수 있다.

6. 특징[편집]

Java의 가장 큰 특징은 플랫폼에 독립적인 언어라는 점이다. 소스 코드를 머신 코드로 컴파일하여 링크하는 C/C++과 달리 바이트코드인 클래스 파일(.class)을 생성하고, 이 파일을 일종의 에뮬레이터인 Java 가상 머신(=JVM)[6]이 해석해서 실행한다.

예를 들어 C 계열 언어들은 윈도우에서 빌드한 프로그램을 그대로 리눅스Mac OS에서 실행하려 하면 일반적으로 오류가 나지만[7] Java로 작성 된 프로그램은 플랫폼에 맞는 JVM만 설치되어 있다면 문제 없이 동작한다. 이는 Java 코드 자체가 플랫폼 종속적이 아니고 가상 머신 종속적이라는 점, 그리고 프로그램 실행의 주체가 운영체제가 아닌 JVM이기 때문이며 이러한 점을 통틀어 플랫폼 종속성이 낮은 언어라고 표현한다.

참고로 JVM 기반의 프로젝트에서는 하나의 언어만을 고집하지 않는다. 스크립트 언어가 유리(간결하고 짧은 소스코드)한 부분은 Groovy로 작업하고, 함수형 언어가 유리(최근 유행하는 빅데이터 등)한 부분은 Scala로 작업하며, 견고한 인터페이스와 대규모 통합이 필요한 곳은 Java로 작업한 뒤 이들을 서로 합쳐서 운영하는게 가능하다. (Java에서 만든 객체를 Scala에서 그대로 사용하는게 가능하다.)

실제 현업에서는 Java와 통합해서 몇몇 인기 언어가 자주 사용되므로 장단점을 잘 알아두는게 좋다. '내가 사용하는 언어를 까는건 참을 수 없어!' 라는 태도 보다는 환경이나 주어진 작업의 특성에 따라 적합한 언어를 선택할 수 있는 지혜가 필요하다.

6.1. 장점[편집]

6.1.1. 수많은 개발자와 레퍼런스[편집]

오래되었고 다른 최신의 언어에 비해서 여러가지로 욕먹는 자바가 그래도 항상 상위권을 유지하는 이유는 바로 수많은 개발자와 레퍼런스를 보유하고 있다는 점이다. 타 언어를 전문적으로 사용하는 개발자들도 Java 정도는 할 줄 안다고 할 정도로 배우기 쉽고 대중적이다. 또한 워낙 오래되고, 대중적인 언어라서 참고자료나 오픈소스가 많고 수많은 대형 프로젝트들이 진행되어왔기 때문에 많은 부분에서 안정성이 입증되었다. 즉, 안정적인 인력풀을 유지하면서, 알려진 위협을 제거하고 운영 노하우를 극대화 시킬 수 있는 검증된 언어라는 것.

6.1.2. 비교적 높은 생산성[편집]

오늘날 프로그램의 덩치와 다루는 것들이 크고 복잡해지면서 생산성과 퍼포먼스 문제가 생기게 되었는데, C/C++ 같은 언어는 생산성이 너무 떨어지고 관리도 힘들어서 프로그램이 커지면 커질 수록 작업이 힘들어지게 된다. 그리고 아무리 컴퓨터 하드웨어가 발달한다고 해도 성능이 더 좋아지면 점점 더 복잡한 것을 다루고, 그것이 새로운 표준이 되면서 하드웨어의 속도 향상이 무색해지기 때문이다. 거기다 리소스를 많이 낭비하는 하이 레벨 언어라면 더 심각하다. 그런데, 그 와중에 나타난 게 바로 Java다. C/C++와 비슷한 문법으로 진입 장벽도 낮고, 객체 지향을 적극적으로 사용하며, 로우 레벨 작업들을 자동으로 처리해 주는 하이 레벨 언어이면서, 퍼포먼스도 다른 하이 레벨 언어들에 비해 빠른 편이다. 거기에 호환성까지! 등장하자마자 순식간에 대세가 된 것도 무리는 아니다. 다만 막강한 스펙을 가진 최신 언어에 비해서라면 자바의 생산성은 상대적으로 낮은 편이다.

6.1.3. 기기 호환성[편집]

장점으로는, 해당 운영체제Java 가상 머신을 설치하면 Java로 만든 프로그램은 어떤 컴퓨터에서도 완벽히 똑같이 동작한다. 가상 머신이 각각의 운영체제에 맞춰서 결과적으로 완벽히 똑같이 돌아갈 수 있도록 제작되는 덕. 가상 머신 없는 운영체제라면 아예 Java 프로그램을 사용하지 못하겠지만, 썬 마이크로시스템즈는 주요 OS용의 가상 머신을 발표하고 있고, IBM, 휴렛팩커드 등의 회사는 직접 자사 운영체제용 JDK/JVM 을 제작하여 발표하며, 이들과 상관없이 독립적으로 특화된 성능향상 기능을 가진 JVM을 만들어서 발표하는 회사도 존재한다. 그래서 이 부분은 보통 단점으로 꼽히지 않는다. 오히려 여러 운영체제에 발벌리는 업체라면 윈도우용, 맥용 등을 따로 제작할 필요 따위가 없이 그냥 하나 만들면 끝!이라고 Java 초창기 홍보되었다.

그러나 다른 크로스 플랫폼 언어들과 마찬가지로 각 플랫폼마다 미묘하게 기능이나 작동에 차이가 있는 부분이 극히 일부분이지만 존재하기 때문에, 이러한 부분을 고려하지 않고 작성된 프로그램을 그대로 다른 데에서 돌릴 때에 문제가 발생할 가능성이 존재한다. JVM의 장점은 그나마 이런 부분들이 다른 언어에 비해서 매우 적은 편이라는 점이다. 이런 경우, 대부분 크로스 플랫폼으로 작성된 코드가 그러하듯 타겟 플랫폼을 인지하여 특정 플랫폼에서는 다르게 동작하게 하는 식으로 코딩을 하게 된다. 주로 java.nio 패키지에 속한 API 에서 이러한 경우를 발견할 수 있으며, OS X 에서만 일부 특이하게 동작하는 MIDI 관련 API 또한 이러한 경우에 속한다. Java의 모토는 Write once, run everywhere[8]인데 프로그래머들은 이를 비꼬아 Write once, test everywhere[9]라고 말하곤 한다.

C 나 C++ 에서도 크로스 플랫폼 형태로 소스코드를 작성하는 것이 가능하기는 했지만, 개발자가 타겟 플랫폼과 해당 플랫폼용 바이너리 코드를 생성하는 컴파일러에 대해서 잘 이해하고 나서 #define, #if 등 전처리기를 써서 각 타겟 플랫폼에 맞게 동작하도록 코드를 직접 작성해줘야 했다. 이와 달리, Java는 단일 소스코드를 컴파일하여 생성된 바이트코드 클래스 파일을 JVM이 존재하는 환경이라면 어디서나 (대부분은) 추가 컴파일이나 수정작업 없이 그대로 똑같이 실행할 수 있다는 점이 차이점이다. 기업 입장에서는 컴파일된 바이너리가 크로스 플랫폼을 보장해주는 Java는 매력적인 언어였다. 오픈소스 진영에서는 Java 초기에 직접 GNU 등에서 컴파일러 구현을 시도했으며, 아파치 소프트웨어 재단 등에서 만든 수많은 오픈소스 프로그램과 라이브러리가 존재한다.

6.1.4. 안정성[편집]

다른 언어에 비해 높은 안정성을 꼽고 있다. 우선 C나 C++에 안정성 문제가 제기되는 포인터 연산자 및 메모리 직접접근 함수들을 지원하지 않는다. 여기에 C++과는 다르게 다중 상속을 허용하지 않는다. 이는 객체지향의 특성 중 하나인 '상속'의 자유도를 확 떨어트리는 것이기에 언뜻 보기에는 객체지향적 관점에 위배되는 것처럼 보일 수 있으나, 반대로 오히려 이게 더 객체지향적이라고 볼 수도 있다. 객체지향의 목적 자체가 재사용을 통한 생산성의 향상과 관리 상의 이점인데, 다중 상속은 잘못 사용할 시 극도로 복잡하게 꼬인 프로그램을 만들 위험성을 갖고 있다. 물론 코드 관리의 측면에서도 다중상속에 의해 발생하는 문제는 좋지 않다. 수준 높은 프로그래머라면 이 문제도 잘 해결할 수 있지만, Java는 아예 미연에 방지하기 위해 다중상속을 언어 스펙에서에서 제거하는 방법을 택했다. 어차피 Java에서는 다중 상속을 포기함으로써 생기는 문제를 interface를 다중 구현할 수 있도록 하여 어느 정도 해결하기도 했다.

메모리를 대용량으로 사용하는 프로그램에서 상대적으로 C, C++ 보다 안정적인 모습을 보일 때도 있는데, 이런 경우에 JVM이 시작될 때 필요한 메모리를 먼저 통으로 잡아버리기 때문이다. 메모리를 많이 쓰는 C, C++ 로 된 프로그램은 실행되면서 필요에 따라 메모리를 동적으로 할당받게 됨에 따라 오히려 Java 보다 버벅거리는 모습을 보여줄 때도 있다.[10] 다만 이는 메모리 할당자 없이 매번 힙 영역 메모리를 할당하는 경우에 해당하는 말이고, 실제로는 jemalloc 등 커스텀 메모리 할당자를 사용하여 이런 문제를 방지하는 것이 일반적이다.

6.1.5. 소스 코드 가독성[편집]

고급 프로그래밍 언어가 만들어진 첫째 목적은 '좀 더 인간 친화적인' 코드의 작성을 돕는 데 있다. 기계어어셈블리어로 진화하고 그것이 C언어로 진화한 배경에는 '사람이 더 쉽게 읽고 이해할 수 있는 코드'가 있다. Java는 동시기에 발표된 다른 언어에 비해 코드가 명료하고 가독성이 뛰어났다. 특히 C++은 특유의 어려움으로 인해[11] 코드가 어셈블리어보다도 더 읽기 힘들 정도로 암호화(!)가 되는 경우가 있다. 특히 C++의 연산자 오버로딩과 템플릿 메타프로그래밍 개념이 코드 난독화에 결정타를 날렸는데 Java는 연산자 오버로딩을 배제하고 오로지 메소드를 통해서만 객체의 조작을 허용함으로써 코드의 일관성을 지켜냈다.[12]

템플릿 메타프로그래밍의 주 사용 용도인 제네릭 프로그래밍도 제네릭이라는 더 쉬운 개념을 도입해서(Java 5부터 지원) 코드의 가독성을 해치지 않고 제네릭 프로그래밍을 성공적으로 도입했다.[13] 키워드에 약어 사용을 자제한 점도 코드 가독성 상승에 기여했다.

6.2. 단점[편집]

6.2.1. 속도 문제[편집]

속도 관련문제는 하드웨어의 성능이 점점 좋아지고 메모리 가격이 떨어지면서 희석되고 있다. 처음 Java가 나왔을때인 1995년만 하더라도, 느린 성능 때문에 그다지 많이 쓰이지는 않을 것이라고 예상했지만, 현재 자바가 가장 많이 사용되는 곳은 상대적으로 성능이 중요하게 생각되는 서버와 모바일 기기이다.

거기다가 밑에 성능 문제가 많이 강조되다보니 Java가 엄청 느린 것처럼 나와있자만, 사실 문제 있는 수준은 아니다. 밑에서 저렇게 많이 까여도 다른 고수준 언어들에 비해서 훨씬 빠른 편인 것을 기억하자. Java가 C보다 2~3배 느리다고 하지만 요즘 인기있는 Python은 C보다 수십배 (심하면 70배 정도) 느리다. 그나마 빠르다고 하는 JavaScript도 Java에 비해서 2배 정도 느리다. 그러니 밑에 설명은 왜 C/C++보다 조금 느린지에 대해서 참고하도록 하자.

6.2.1.1. JVM 로딩 속도문제[편집]

Java의 심각한 단점 중 하나는, 실행하는 과정에서 가상 머신이 반드시 완벽하게 로딩하여 실행해야 하기 때문에 프로그램의 초기 시작 시간이 완전한 이진 코드로 컴파일된 프로그램을 실행하는 것에 비해 오래 걸리는 것이다. 단적인 예로, 아무것도 안하고 콘솔 화면에 달랑 "Hello, World!" 라고 찍기만 하는 프로그램이 실행되는 데에도 thread가 10개 쯤 뜬다. 특히 그 프로그램에 AWT, Swing, SQL 같이 불필요한 기능을 끌어들이는 것은 매우 심각한 문제이다. 이 문제는 런타임 자체가 아직 모듈화되지 않았다는 점에서 기인한다.

하지만 요즘 같은 고사양 컴퓨터에서는 많은 라이브러리를 끌어오는 것이 아니라면 체감상 차이는 크게 나지 않는다. 또한 Java 9에서는 런타임 라이브러리를 아예 모듈화하고 있으므로, 필요한 모듈만 끌어서 프로그램을 짤 수 있다.

6.2.1.2. 가상 머신 바이트코드 실행 속도 문제[편집]

C, Pascal, Fortran 과 같은 언어와 달리, 바이트코드로 된 프로그램을 실행하려면, 운영체제와 프로그램 사이에 JVM 이라는 두꺼운 계층이 하나 더 자리잡게 된다. 그리고 바이트코드는 실시간으로 각 타겟 플랫폼용 기계어로 번역되어 실행된다. 이로 인해 네이티브 바이너리 코드를 출력하는 언어와 비교하여 실행속도와 성능에 일정부분 손실이 발생할 수 밖에 없다. 이런 문제점을 썬 마이크로시스템즈도 곧 깨달았고, 최초 발표에서 2년 후인 1998년 부터 JIT 컴파일러를 JVM에 내장하고 성능을 개선하고 있다.[14] 하지만, 그만큼 메모리가 뒷받침해줘야 한다. 현재는 보통 같은 기능/알고리즘을 실행하는 데 C++ 보다 2 ~ 3배 정도 시간이 더 필요하다고 알려져 있다. 이 부분은 꽤 초기부터 지속적으로 개선되어 왔기 때문에 현재 실행속도 자체에 대한 이슈는 예전에 비해 많이 줄어든 편이다.

또한 Swing이나 AWT를 이용해서 큰 규모의 GUI 프로그램만 만들어도 심각하게 느린 것을 체감할 수 있다. 그런데 정작 상용 프로그램으로 배포되는 것을 보면 AWT, Swing 대신 이클립스의 SWT 또는 넷빈즈의 자바 플랫폼에 기반하여 개발하거나, 이것도 아닌 제3의 UI 또는 그래픽 라이브러리를 사용한다. 그래서 마인크래프트가 렉이 많이 걸렸냐 그건 마인크래프트가 최적화가 잘 안돼서 그래[15]

이 문제는 Java 9에서 '선행 컴파일'이라는 이름으로 대폭 개선될 예정이다. 바이트코드를 거칠 것 없이 바로 기계어로 번역하면, 호환성을 잃는 대신 속도는 대폭 개선될 수 있게 된다. 이에 따라 핵심적인 부분을 제외한 나머지는 더 이상 JNI를 거칠 필요가 없다.

6.2.1.3. 가비지 컬렉션에 의한 실행 지연문제[편집]

가비지 컬렉션에 의한 메모리 프리징 현상[16]이 초반부터 지속적으로 Java를 괴롭혔다. 멀쩡하게 동작해야 할 프로그램이 순간적으로 뚝 뚝 끊기는듯한 현상이 발생한 것. 이는 실행속도와 함께 Java 초기부터 꾸준히 문제로 꼽혀온 것으로, 버젼이 올라갈 때 마다 다양하게 개선되었고, Java 8 에서는 메모리 모델과 가비지 컬렉션에 획기적인 개선이 있었다.

6.2.2. 불편한 예외 처리[편집]

그리고 프로그램을 돌리다가 프로그램이 의도된대로 동작하지 않는 상황에서 예외를 발생시켜 처리를 할 수 있다. 대부분의 언어에서 차용하고 있는 좋은 기능이지만... 유독 Java는 다른 언어와는 달리 프로그래머 검사가 필요한 예외가 등장한다면 무조건 프로그래머가 선언을 해줘야 한다. 그렇지 않으면 컴파일조차 거부한다. 원래 의도는 철저한 예외 처리를 하니까 만약에 발생할 수 있는 모든 상황에 안정성을 확보할 수 있겠지...였으나, 결국 많은 경우엔 조낸 귀찮다는 이유로, 가장 일반적인 예외(Exception 더 막나가면 Throwable) 하나만 써서 넘어가버리고[17] 폭탄 돌리듯 넘기기만 하거나(예외 던지기만 하고 try catch 안하면 메소드 를 돌고돌다가 콰광!) , 예외 나든 말든 무시해 버리는 경우가 가장 흔하다.[18] 이런 코드가 너무 흔해 빠진 나머지 이딴 식으로 쓸 거면 왜 넣었냐고 까는 사람도 많다. 그런데 선언 필요없는 검사 안하는 예외도 Java에 많다(...).[19] 그리고 C++이나 C# 같이 예외가 있는 언어라도 Java처럼 예외를 쓰는 경우는 별로 없다. 두 언어는 모든 예외가 검사 안하는 예외이다. 사실 예외 처리를 한다는 것은 귀차니즘과 견고함을 맞바꾸는 일인데, 안할 사람은 문법으로 강제해도 안한다는 것을 보여준다(...)

대부분의 다른 언어에서는 원하는 에러만 try-catch문으로 뽑아내고 그렇지 않은 경우에는 그냥 아무 처리를 해주지 않아도 된다. 이러한 언어를 접하던 사람이 Java를 접하면 그 특유의 경직된 예외처리에 불편해하기도 한다. 오히려 명시적으로 예외처리를 할 수 없는 경우도 존재하는데, 인터페이스를 상속받을 때 인터페이스에 선언된 예외가 아니면 구현클래스에서 그 예외를 던질 수 없다! 특히, Java에서 제공하는 Iterator 인터페이스에는 throws 선언 따위는 없기 때문에 Iterator를 구현받았을 때 명시적으로 예외를 던질 수 없다. 이 상황을 해결하려면 RuntimeException 계열을 쓸 수밖에 없는 상황이 펼쳐진다.

다만, 상기의 내용은 실무적 접근에 의한 내용이고, 실제로는 이는 장점으로도 취급되기도 한다. Assert문을 자유자재로 쓰면서 예외처리를 하거나 코딩과 동시에 발생할 수 있는 각종 예외들을 인지하고 처리해주는 걸 잊어먹는 경우에 대한 대처가 가능하다.[20]

6.2.3. 소스 코드 길이[편집]

Java는 소스 코드의 길이가 다른 언어에 비해 상당히 긴 편이다. 같은 기능을 하는 코드를 짠다고 했을 때 Java만큼의 고생산성을 발휘하는 다른 언어에 비해 타이핑해야 할 양이 많다.

인터프리터 언어에서는 puts("Hello") 정도로 끝났을 일을 Java에서는

public class HelloWorld {
  public static void main(String[] args) {
   System.out.println("Hello");
  }
}

이만큼을 써야 한다. 같은 일을 하는 C언어 코드는
#include <stdio.h>
int main() { 
  printf("Hello\n");
return 0;
}

파이썬의 경우
print("Hello")

위키책에 있는 Hello World 프로그램의 목록이나, 나무위키 내의 프로그래밍 언어/예제 문서를 보면 고생산성언어 중에서는 코드양이 긴 편인 걸 알 수 있다.

오죽하면 이런 생소멸자 까지는 봐줄만 하다가 try-catch나왔을때 언제 이색* 만나면 잡아 족쳐야 한다 라고 생각한 위키니트들은 피식 웃어주기를 바랍니다.포스트가 만들어질까. 물론 이건 Java의 문제가 아니고 마세라티 문제라고 알려진 프로그래머의 과욕이 부른 참상이지만 코드에 유연성을 조금 추가하기 위해 써 넣어야 할 코드의 길이가 기하급수로 증가한다는 하나의 예시로 볼 수 있다. 참고로 저 포스트의 5년차 코드는 스프링 프레임워크의 패러디다. Java 이후에 나온 차세대 언어들은 같은 수준의 유연성을 확보하기 위해 들여야 할 노력의 양이 훨씬 적다.

물론 다른 언어보다 쉽게 만들 수 있는 것들도 많다. 예를 들어 창(Window)을 만들 때는 JFrame을 상속 받아 간단하게 가로 세로 500인 창을 만들어 보자면
setSize(500,500); // 창 사이즈
setTitle("프레임창"); // 창 이름
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // X버튼 누르시 프로그램 종료 만약에 이런 것 하지 않으면 종료해도 완전히 종료되지 않아 그대로 상추할 것이다.
setVisible(true); // 창 보이기

이렇게 4줄만 쓰면 창을 생성할 수 있다. 하지만 정말 창말고는 아무것도 안 나온다.

사실 이건 Swing의 장점이지 자바의 장점은 아니다. 그렇게 따지면 C#Windows Forms로는,
Size === new Size(500, 500);
Text === "프레임창";

2줄로 끝이다.

게다가 다른 고수준 언어(C#, Python, Ruby 등)에 비해서 문법적 설탕(syntactic sugar)이 적어서 이쪽에서 넘어오면 꽤 불편해하는 편. 하지만 최근 Java 8로 넘어오면서 람다 표현식, Stream [21] 등을 지원하는 식으로 문법적 편리함을 늘려가는 추세다. 이 흐름은 다음 Java 9 에서 더욱 강화될 것으로 보는 추세.

그러나 꼭 명심해야할 점은, 무조건 타이핑의 양이 많다고 해서 나쁜 것만 있는 것이 아니다. 일단 Java는 명색이 클래스지향적이기 때문에 어쩔 수 없는 부분이며 프로젝트 단위의 큰 단위에서 봤을 땐 오히려 읽기가 편하기 때문에 말할 것도 없이 작업속도가 빨라진다. 축약어의 사용을 최대한 자제하는 방향으로 만들었기 때문에 그렇다. 그리고 IDE에서 기본적으로 코드를 자동생성해주기 때문에 코드의 길이로 장단을 판별할수는 없다. 오히려 파이썬의 경우 dynamic 타입 때문에 파일 하나 가지고 장난치기엔 좋겠지만 프로젝트로 가면 머리 아파진다.

6.2.4. 언어적 불편함[편집]

6.2.4.1. 명사형 생각을 강제[편집]

Java는 모든 동작이 객체 상위에서 이루어지게 함으로써 명사형으로 생각하는 것을 강제한다. 그 결과로 Java에는 전역 함수가 없고 모든 함수는 어떤 클래스에 종속되어있다. 이 때문에 기능적인 부분을 작성하는데 자잘한 클래스들을 작성해야 한다는 불편함이 있다.

이런 명사 중심적 생각은 확실히 많은 경우 편리하나 동사 중심으로 생각해야하는 상황도 생각보다 흔하다는게 문제. 예를 들어서, 퀵소트를 Java에서 엄격하게 의도된 대로 짜려면 QuickSort(array)라는 함수 대신에 Quicksorter라는 오브젝트의 생성자에 배열을 넣고 run()을 호출하여 동작을 하게 해야 하는 것이다.

디자인 패턴을 사용해서 어느 정도 동사형 사고방식으로 코드를 작성할 수 있긴 하다. 디자인 패턴에서 핵심적 지위를 차지하는 인터페이스라는 놈을 사용하면 상당히 동사적인 관점으로 객체를 다룰 수 있다. Java의 리플렉션 API를 사용하는 방법도 있고. 하지만 언어가 애초에 생겨먹은 것 자체가 명사 기준으로 생각하게 디자인된 건 사실이다. Java의 근간을 이루는 표준 java.lang 클래스와 java.util 클래스를 동사형 사고방식으로 재작성하기 전에는 힘들다. 물론 이 재작성 삽질은 이미 Scala언어에서 해놨으므로 여러분은 또 삽질할 거 없이 Scala쓰면 된다.

6.2.4.2. 클로저 미지원[편집]

명사형 생각을 강제 한다는 것의 연장선. Java에서 함수는 일급 객체로 취급되지 않는다. 어떤 '동작'을 넘겨야 할때는 그 동작을 추상화한 인터페이스를 만들고 -> 그것을 구현한 뒤 -> 객체를 파라미터로 넘겨야한다. 반면에 클로저를 지원하는 언어는 그냥 함수를 파라미터로 넘기면 된다.

Java 8에서는 람다 표현식을 지원함과 더불어 Function, 즉 함수를 멤버 표현이라는 방식(this::add) 으로 다른 함수의 파라미터로 넘길수도 있다. 다만 이 역시 자유롭지 못하고 파라미터로 넘겨지는 함수의 매개변수, 반환형이 단 한개씩으로 정해져 있어야 하며 void 형의 (리턴이 없는) 반환형을 지원하지 않는다. -> Functional Interface는 수십여 종이 있으며 인자가 복수개인 것도 당연히 있고, 하나의 추상 메서드를 가진 인터페이스를 새로 만들어서 써도 된다. 또한 리턴이 없는 Functional Interface로는 Consumer<T>가 있다.

클로저 미지원 문제 때문에 저 수많은 디자인 패턴들이 만들어졌다. Java라는 언어가 설계될 당시에는 클로저라는 개념 자체가 LISP, Haskell, ML 등의 언어을 사용하거나 프로그래밍 언어를 연구하는 사람들이나 아는 몹시 마이너한 개념이었기 때문에 동시기에 만들어진 다른 많은 프로그래밍 언어들도 클로저를 지원하고 있지는 않았다. 따라서 설계 결함이라고 부를 수는 없고 현대에 들어서 단점으로 부각되기 시작했다는 편이 더 적절하다.

7. 개발환경, JVM 언어[편집]

7.1. 개발환경[편집]

Java에 특정한 라이브러리를 가미해서 웹에서 돌릴 수 있게 한 것이 Java 애플릿이다. 애플릿 특유의 제약으로 인해 ActiveX보다는 훨씬 안전하다는 이유로 물 건너에서는 인터넷 뱅킹이나 결제용도로 사용하기도 한다. 근데 상대적으로 안전하다는 것일 뿐, 애플릿을 사용한 결제시스템도 툭하면 뚫려서 문제가 발생하곤 한다(…). 더군다나 아이폰안드로이드에서는 되지 않는다. 게다가 크롬과 파이어폭스 등의 브라우저들이 NPAPI 지원 중단 선언을 하면서 애플릿의 살 길이 막막해졌다.

웹 애플리케이션 제작을 위해 Java 언어를 사용하는 규격으로 Java 서블릿과 JSP(Java 서버 페이지)가 있다.[22] 주로 기업에서 사용한다. 개인 웹호스팅에서는 이를 지원하는 경우는 많지 않다. 그러나 최근 Java 를 지원하는 여러 클라우드 컴퓨팅 서비스가 싼 가격에 등장하고 있고, Java 뿐만이 아닌 JVM 언어를 이러한 환경에서 구동하는 사례가 늘고 있다.

오라클에서 제공하는 Java Development Kit(Java 개발 도구)를 설치하면 javac란 컴파일러가 제공된다. 하지만 통합 개발 환경은 제공해 주지 않기 때문에, 반드시 별도의 개발용 프로그램을 써야 한다. 대표적으로 이클립스, 넷빈즈, IntelliJ IDEA 등이 있다. 만약 이것을 안 쓰겠다고 한다면, 당신에게는 메모장과 javac.exe가 있을 뿐이다. 그리고 Java는 IDE 없이 타이핑만으로 짜기엔 굉장히 불편한 언어라는 것을 명심하자.[23] 실전 Java 개발을 할 때 프로젝트에 필요한 라이브러리 관리나 프로젝트 결과물 배포 등 프로젝트 빌드 관리를 위한 도구로는 아파치 재단에서 만든 Ant와 Maven이 많이 사용되고 있다. 최근에는 이 두가지의 단점을 보완한 Gradle이 각광을 받고 있으나 국내에는 아직 많이 쓰이지는 않는 듯하다.

TDD 개발을 위한 방법으로는 Jenkins를 통한 CI 관리, Sonar를 통한 코드 분석, Maven을 통한 빌드 관리, Jacoco를 통한 Code coverage 관리 방법을 사용할 수 있다.

7.2. JVM 언어[편집]

이외에 Java와 똑같이 Java 바이트 코드를 생성하지만 언어 규격이 다른 ScalaClojure라는 언어들도 있다. Scala는 'Scalable Language'에서 따왔는데, Java와 비슷한 부분이 많으며 Java API를 그대로 가져다 쓸 수도 있다. 또한, syntactic sugar가 많고 함수형 프로그래밍의 여러 가지 요소들을 가져와서 Java에 비해 생산성도 높다. 일례로 일일히 타입 추론을 var x === 1.5와 같이 넣으면 알아서 float 형으로 추론해준다.[24] 또, switch-case의 확장판이라 할 수 있는 패턴 매칭을 지원하며 클로저도 지원된다. 단점으로는 이런 고수준-고생산성의 언어에서 많이 볼 수 있듯이 같은 Java 코드에 비해 약간 느리다. Clojure는 Java 플랫폼에서 동작하는 LISP 방언으로 설계되었으며 Common Lisp와 Scheme과 함께 주요 LISP 방언 중 하나로 꼽힌다. 이 언어도 마찬가지로 Java API를 가져다 쓸 수 있다.

Java 6부터 Scripting API라는 것이 추가되었다. JVM 언어 구현체에서 javax.scripting 관련 API를 제공하면 Java 코드에서 동적으로 인터프리터를 생성하고 연동하여 사용할 수 있게 해주는 표준 API 이다.

7.2.1. 유명한 JVM 언어 목록[편집]

아래에 나열된 언어들이 유명하며, Common LISP, Scheme, Pascal 등 여러 다양한 언어들이 구현되어 있다.

  • Clojure

  • Groovy: Java에 Python, Ruby, SmallTalk 등의 특징을 버무린 동적 타입 언어. 2003년에 등장했다.

  • JRuby: 루비의 대부분을 Java로 구현한 언어 구현체. 역시 호환된다.

  • Jython: 파이썬의 Java 구현체. JVM 위에서 동작하며, 따라서 Python 모듈과 함께 Java 클래스, JAR 사용이 가능하다. 참고로 로고는 Java의 커피 컨셉과 Python의 뱀 컨셉을 섞어서 커피잔에서 이 연기처럼 피어나오는 로고다(...)

  • Kotlin : IntelliJ IDEA를 만든 JetBrains에서 개발한 언어이다.Google I/O 2017에서 Android Studio 3.0부터 공식언어로 정의되었다.[25]

  • Rhino: JVM로 돌아가는 JavaScript 엔진으로, 모질라 재단이 100% Java로 개발했다. JavaScript와 Java의 API를 동시에 사용해 개발할 수 있다. Java 7 에 내장되어 있다.

  • Nashorn: 또 다른 JVM 위에서 돌아가는 JavaScript 엔진이다. Java 8과 함께 등장했다. 참고로 Nashorn 은 Rhino(코뿔소)의 독일어다.

  • Scala

7.3. 유사품에 주의합시다[편집]

  • 유사품 A : 자바스크립트(JavaScript)
    JavaScript는 이 Java와는 아무 상관도 없다. 넷스케이프사에서 Mocha, LiveScript로 개발하던 스크립트 언어를 1996년 전후 열풍이던 Java의 유명세에 묻어가기위해 Sun에서 상표권을 라이선스해 JavaScript라고 이름붙였을 뿐이다. 이름 하나 생각없이 잘못 붙여서 여러 사람 지금도 헷갈리게 만든 대표적인 케이스.
    이름 말고는 언어 성격 상 연관성은 희박한 편이다. 문법조차 별로 비슷하지도 않으며, 사용되는 라이브러리나 개념 또한 많이 다르다. 기초 패러다임상 당연한 요소들을 제외하고 나면 둘의 유사점은 오직 객체지향 뿐인데 그 마저도 JavaScript는 프로토타입 베이스라 클래스를 쓰는 Java와 많이 다르다. (하지만 ECMAScript 6에서 Class가 생겼다!) 또 Java는 컴파일 언어이지만[26] JavaScript인터프리터 언어다. 그나마도 요즘은 둘 다 JIT로 통일되어가는 추세다. 여담으로 JavaScript에 JIT를 최초로 도입한 브라우저는 다름아닌 크롬.
    떠도는 말로 'Java와 JavaScript의 차이는 인도인도네시아의 차이와 같다'라고도 한다. 간혹 인도와 인도네시아의 차이를 이걸로 설명하는 사람도 있다. 왜냐하면 인도인도네시아가 이름만 비슷하고 서로 다른 국가이듯이 Java와 JavaScript도 다른 프로그래밍 언어이기 때문이다.
    참고로 이 JavaScript의 표준안에 대한 정식 명칭은 ECMAScript다.

  • 유사품 B : Visual J++/Visual J# -> C#
    Visual J++은 마이크로소프트에서 Java를 변형하여 윈도우 전용으로 만든 언어. 위의 JavaScript는 이름만 바꿨지만 이건 Java 자체를 윈도우에 맞도록 변형한 것이다. 이 때문에 Java 가상머신 없이 윈도우에서 네이티브로 돌아가지만, 다른 플랫폼에서는 전혀 돌아가지 않는다. 거기다 썬 마이크로시스템즈의 허락없이 마구 변형해서 썼기 때문에 소송크리를 먹고 개발이 중단되었다.
    이후 윈도우의 프로그램이 닷넷으로 넘어가면서 닷넷 기반의 Visual J#도 만들었다. Visual Studio 2005에 포함되었지만 이것도 개발이 중단되었다. 이때는 썬이 소송하지도 않았는데 중단된 것을 보면 시장성이 없었던 듯 하다. 그리고 지금은 남은 게 C#밖에 없다.

8. 불투명한 미래?[편집]

오라클이 자바를 포기하려고 한다는 주장이 있다. "Oracle Mysteriously Fires Almost All of Its Top Java Evangelists"(Softpedia News) "자바 에반젤리스트, 오라클 퇴사의 변 "자바 구하려""(ZDNet Korea)

자바 에반젤리스트는 자바의 전체적인 업계 내에서의 분위기를 결정지을 수 있는, 비교하자면 리눅스계의 리누스 토발즈 같은 사람들인데, 오라클이 이 사람들을 꾸준히 해고하고 있다는 것이다. 장사를 독하게 하기로 유명한 오라클인지라, 자바 자체가 지금은 물론이고 미래에도 그다지 수익성이 좋다고 할 수 없기에 망설임 없이 포기하려는 것이 아니냐라는 관측이 있다. 제임스 고슬링도 한마디 했다.

다만 이 부분은 굉장히 사람에 따라 극단적으로 반응할 수도 있는 문제이므로[27] 업계 분위기에 대한 판단은 스스로 하도록 하자.

2017년 8월 17일, 오라클이 자바 EE를 포기한다고 발표했다. 오픈오피스, 넷빈즈 때와 같이 오픈 소스 생태계로 보내려 하고 있으며, 아파치 소프트웨어 재단이클립스 재단이 자바 EE를 넘겨받을 유력한 후보로 알려져 있다. Opening Up Java EE 이후 이클립스 재단이 맡는 것으로 확정되었고, 자바 EE의 오픈 소스화를 위한 9개 프로젝트를 추진한다고 밝혔다. #1#2

9. 여담[편집]

  • Java의 창시자인 제임스 고슬링 옹은 진성 앱등이다.[28] 집에서 쓰는 IT 기기에 대해 묻는 질문에 폰, 타블렛, 데스크탑, 랩탑 등 거의 모든 IT 기기를 애플사 제품으로 도배해놨음이 밝혀졌다. 가족들도 마찬가지. 정작 애플은 OS X 레오파드 업데이트 때 Java를 찬밥 취급했지만...[29]

  • 조엘온 블로그로 유명한 조엘이 엄청나게 싫어하는 언어. 외부링크 조엘 스폴스키가 Java를 싫어하는 이유로는 성능상의 문제나 문법상 너무 쉽다(...)[31]는 이유도 있지만, Java 자체가 "위원회 기술"이라는 이유도 큰 몫을 차지한다. 사실 이는 Java가 가진 태생적 문제인데 Java라는 언어가 C#처럼 어느 특정 단체나 회사가 주도적으로 끌고가는 물건이 아니다 보니 위원회를 구성하는 각 업체들의 파워게임에 따라 중요한 문제의 해결방안이 빨리 처리 되지 않는 경우도 있고 배가 산으로 가는 경우도 있다. 더 심각한 점은, 위원회를 구성하는 업체들이 승질 나서 자기 멋대로의 Java 언어를 만드는 경우다. 이 경우 자칫하면 똑같은 Java 코드인데 업체별 Java 가상머신에 따라 프로그램이 작동할 수도 안할 수도 있다(...).

  • Java에서 UI를 만들 때도 고려를 해야할 게, Java는 UI를 만들 때 AWT나 Swing 둘 중 하나 혹은 둘 다 선택하여 UI를 만드는 게 가능하다. 조심해야 할 점은, AWT로 생성한 UI는 Swing UI에 가려버린다. 그래서 멀정히 잘 돌아가는 코드인데도 불구하고 배경이 컨트롤(콤보박스라거나)을 가려버리는 일이 있을 수 있다.

  • 가비지 컬렉션을 제공하여 개발자가 직접 메모리의 할당과 해제를 관리해야 할 일이 없지만, 고급 주제로 넘어가면 가비지 컬렉션의 동작 원리를 이해해야 함과 동시에 할당과 해제 사이클을 직접 제어해야 하는 모순적인 상황 또한 제공한다. 그런데 이 정도로 순간적인 freezing에 취약한 물건이면 애초에 C나 C++로 만들지 Java로 안 만든다.

  • Java 클래스 바이트 코드 매직넘버가 0xCA 0xFE 0xBA 0xBE다. 이것을 붙이면 CAFEBABE 다. CAFEBABE인 이유는, 제임스 고슬링과, 다른 연구원들이 St. Michael's Alley 라는 곳에 점심을 먹으러 가곤 했었다고 한다. 그 지방 전설에 의하면 그곳에서 더 그레이트풀 데드라는 밴드가 크게 성장하기 전에 연주하던 곳이라고 했다. 제리가 죽었을때, 불교같은 신사를 세웠다고 한다. 그리고, 제임스 고슬링과, 연구원들은, 그곳을 Cafe Dead 라고 불렀다. 그러다, CAFE DEAD 가 헥스 넘버인것을 알아냈다고 한다.[32] 그때 마침, 그는 파일 포맷 소스와, 매직넘버를 개편하고 있었다.[33] 결국은, Object 파일의 매직 넘버는 CAFEDEAD가 되었다. 나머지 하나, 클래스 파일의 매직넘버는 CAFE다음에 맞을 만한 번호를 정하는 것인데, 그때 적은 것이 BABE다.

  • 2012년 말에는 Java에 보안 취약점이 발견되어 오라클에서 긴급 보안 패치를 발표했지만 또 다른 취약점이 발견돼버리는 바람에 Java를 계속 써야 하나 말아야 하는 논쟁이 벌어지기도 했다. 지금은 잠잠해진 상태.

  • 기존의 32bit용은 64bit 웹 브라우저에 사용할 수 없기에 64bit용 Java가 공개되어 있다. 그러나 32bit 웹 브라우저와 64bit 웹 브라우저를 각각 돌아가며 사용해야 할 필요가 있을 경우 둘 다 설치해야 제대로 돌아가기 때문에 번거로운 편이다.

10. 관련 문서[편집]

[1] 창시자는 제임스 고슬링이다.[2] Internationalization[3] GCC 계열 Java 컴파일러인 GCJ에서는 이미 지원하고 있던 기능이다. Windows는 미지원.[4] 많은 사람들이 착각하는 부분인데, Java는 엄밀히 말하면 완벽한 객체지향 언어가 아니다. 프리미티브(primitive) 타입은 객체로 취급하지 않기 때문. 모든 것을 객체로 취급하는 언어를 순수 객체지향(pure object oriented)이라 하며 이를 지원하는 언어는 Smalltalk가 대표적이다. 최근 만들어진 언어중엔 C#이 이에 해당된다.[5] 실제로, 리누스 토르발스가 C++을 비판하면서 프로젝트에 C++이 아닌 C를 사용하는 이유 중 하나는 C가 좋아서라기보다 C++ 프로그래머들을 의도적으로 배제하기 위해서라고 한 적이 있다. 그러나 퍼포먼스 향상이 필요한 곳에서는 C++를 쓴다 C++의 경우, 고도로 숙련된 프로그래머가 주의 깊게 디자인하고 프로그래밍하지 않을 경우 망측한 코드를 만들어낼 가능성이 매우 높아 제대로 디자인된 언어가 아니라고 주장하였다. 프로그래밍을 해 봤다면 알겠지만, C++ 다루는 프로그래머들은 많지만 C언어에 비해 쉽다고는 생각이 들지 않을 것이다.[6] 바이트코드로 변환된 클래스 파일을 머신 코드로 변환시켜 실행하는 역할을 한다. 좀 쉽게 비유하자면 늘 Java를 따라다니며 필요할 때마다 Java가 원하는 일을 해주는 집사 같은 툴이라고 생각하면 된다.[7] WINE이 설치된 경우는 제외.[8] (프로그램을)한번만 짜고, 어디서나 돌려라[9] 한번만 짜고, 어디서나 테스트해봐라[10] 물론 이는 게임 등 어느정도 사용되는 메모리를 예측하여 제한하는 프로그램이 아닌, 크기를 예측 가능한 빅 데이터를 가공하고 처리하는 프로그램에서 주로 발견되는 차이점이다.[11] '스트로스트롭의 삽질'이라 비꼬는 데도 있다. 물론 C++의 문법 자체가 배우기 어려운 것은 아니고, 처음 프로그래밍을 배울 때는 C부터 배워가는 경우가 많아서 C++로 넘어가는 것도 수월한 편이다. 하지만 문법을 배우는 난이도와, 실제 코딩을 하는 난이도는 다르다.[12] 하지만 연산자 오버로딩은 분명 제네릭 프로그래밍에 도움을 준다. 가령 제네릭 클래스 내에서 주어진 타입의 변수 두 개를 더하는 연산을 하고 싶다면? 더하는 연산 등 여러 일반적인 작업들은 Java의 primitive 타입에만 필요한 것은 아니다. 행렬 등이 그런 대표적인 예다. 이러한 측면에서 본다면 프로그래머의 작업에 있어서의 일관성은 훼손됐다고 볼 수도 있다.[13] 다만 제네릭은 type erasure를 사용하기 때문에 개념적으로 템플릿과 다르며, 할 수 있는 일도 거의 제네릭 프로그래밍 자체로만 한정돼 있다.[14] JIT는 안드로이드에도 오래전부터 사용되어 성능 극대화를 하려했다. 지금은 ART로 넘어가 앱설치할때부터 기계어로 변환시켜버린다.[15] 노치의 발코딩이 원인 맞다. 마인크래프트는 LWJGL를 사용하는데, 이 라이브러리는 속도를 위해 저수준 제어 부분이 C로 구현되어 있고, 이 부분을 JNI로 Java 또는 Kotlin 코드에 붙여서 다양한 기능을 제공하는 형태로 구현됐다. JNI로 한 다리를 건너서 접근하기는 하지만, 똑같은 걸 생짜 자바로 만들어서 굴리는 것보다는 훨씬 빠르다.[16] 메모리를 훑으면서 순간적으로 프로그램이 얼어붙어 멈추는 현상.[17] 이를 gotta catch 'em all 패턴이라고 한다.[18] 물론 이렇게 짜면 안되지만 구조적으로 강요받는 형편.[19] 이쪽은 RuntimeException 계열의 예외로, 이것을 던지는 메소드가 throws에 명시적으로 던진다고 선언하지 않았을 경우 검사를 하지 않아도 된다.[20] 대한민국에 국한되는 경향이 강하긴 하지만 현재 대한민국에서 이러한 예외처리를 코딩하는 순간에 인지하는 개발자는 드물다. 국비지원 학원을 막 졸업한 신입들은 말 할 것도 없으며 현업 몇년 한 초중급 경력자들 역시 이를 인지하지 못하는 경우가 허다하기 때문에 어찌보면 대한민국 IT계의 버그처리와 예외처리에 있어서만큼은 장점으로 볼 수도 있다.[21] 컬렉션(Collection)의 이터레이터를 확장해서 처리할 수 있는 개념으로, 이터레이터의 원소를 필터링해서 원하는 원소만 뽑거나, 원소갯수를 줄여버리고, 이렇게 다시 뽑혀진 원소들로 갖가지 처리를 만드는 등 '함수적인(functional)' 기능을 제공한다.[22] JSP의 목적이 HTML 페이지를 동적으로 만들어내는 것이다. JSP 페이지는 자바 서블릿 코드로 변환되어 서버에서 실행되고, 이 HTML 결과를 브라우저에 보여준다. JSP 페이지는 HTML 페이지에 Java 코드가 포함되어 있는 식으로 되어 있는 경우가 많고, 이 점은 PHP, ASP.NET 등과 비슷한 편이다. 반면 Java 서블릿은 서버 쪽에서 하는 일에 관심이 많지만 출력에 대한 관심은 적다. 필요하다면 브라우저에 출력을 전혀 안 보낼 수도 있다. 최근에는 Server side script language로 HTML 페이지를 동적으로 만드는 식으로는 프로그래밍을 하지 않는다. JSP, PHP와 같은 Server side script language로는 서버에 있는 자원의 접근을 주로 하고(DB 연산, File 연산 등등) 화면에 보여주는 UI는 HTML/CSS/Javascript로만 한다. 이를 위하 Client side와 Server side에 통신이 필요한데 XHR(XML HTTP Request)를 이용한다. 이러한 프로그래밍 기법을 나타내는 표현이 REST내지는 Open API이다.[23] Java는 현용 프로그래밍 언어 중에서는 Verbose한(장황한) 언어로 꼽힌다. 즉, 같은 의미인데 많은 타이핑이 필요하다.[24] 알아서 타입을 추론해준다는 의미. Scala는 Java같이 static typed 언어다.[25] 안드로이드의 자바 라이센스 무단 사용으로 오라클과 법정 싸움을 한 여파로 보인다.[26] Java를 컴파일 언어라고 보기에도 다소 어려운 부분이 있다. 자바 소스를 class로 만드는데는 컴파일이지만, class를 실행하려면 인터프리터의 동작을 한다. 따라서 컴파일 언어라기보단 하이브리드 언어가 맞다.[27] 각 언어 프로그래머들의 자신의 언어에 대한 자부심은 가히 종교의 신앙과 비견할 만한 것이다.[28] Java가 안드로이드OS의 기반이 되는 언어라는 점을 생각하면 아이러니..[29] 사실 애플은 독자적인 JDK를 제공하는지라 자바 개발자들을 매우 피곤하게 하는 회사이기도 하다. [30] 단지 징역을 살지는 않고 FBI에서 1년 근무하는 것으로 퉁쳤다. [31] 이 부분은 대학의 교육용' 언어로서의 이야기다. 산업용으로서는 같은 기능을 개발하기 위한 언어는 쉬우면 쉬울수록 좋은것이 당연하다. 물론 성능과 생산성 사이에서 적절한 균형을 잡아야 하지만.[32] CAFEDEAD 를 0xCA 0xFE 0xDE 0xAD로 바꿨을 때의 얘기인듯 하다.[33] 그때 필요한 매직넘버는 2개였다. 하나는 오브젝트 파일이고, 또 다른 하나는 클래스 파일 매직넘버였다.