왜 Project Jigsaw / JPMS입니까?


80

Java의 패키지 관리 시스템은 항상 간단하고 효과적이었습니다. JDK 자체에서 많이 사용됩니다. 우리는 네임 스페이스와 모듈의 개념을 모방하기 위해 그것을 사용하고 있습니다.

Project Jigsaw ( Java Platform Module System 이라고도 함) 는 무엇 을 채우려 고합니까?

공식 사이트에서 :

이 프로젝트의 목표는 Java SE 플랫폼을위한 표준 모듈 시스템을 설계 및 구현하고 해당 시스템을 플랫폼 자체와 JDK에 적용하는 것입니다.

답변:


101

Jigsaw와 OSGi는 동일한 문제를 해결하기 위해 노력하고 있습니다. 조잡한 모듈이 내부를 보호하면서 상호 작용하도록 허용하는 방법입니다.

Jigsaw의 경우 조잡한 모듈에는 Java 클래스, 패키지 및 해당 종속성이 포함됩니다.

여기에 예가 있습니다 : Spring과 Hibernate. 둘 다 타사 JAR CGLIB에 종속되지만 해당 JAR의 서로 다른 호환되지 않는 버전을 사용합니다. 표준 JDK에 의존하면 무엇을 할 수 있습니까? Spring이 원하는 버전을 포함하면 Hibernate가 중단되고 그 반대의 경우도 마찬가지입니다.

그러나 Jigsaw와 같은 더 높은 수준의 모델이있는 경우 다른 모듈에서 다양한 버전의 JAR을 쉽게 관리 할 수 ​​있습니다. 상위 레벨 패키지로 생각하십시오.

GitHub 소스에서 Spring 을 빌드 하는 경우에도 볼 수 있습니다. 프레임 워크를 다시 작성하여 코어, 지속성 등 여러 모듈로 구성됩니다. 애플리케이션에 필요한 최소한의 모듈 종속성 집합을 선택하고 나머지는 무시할 수 있습니다. 이전에는 모든 .class 파일이 포함 된 단일 Spring JAR이었습니다.

업데이트 : 5 년 후-Jigsaw 에 해결 해야 할 몇 가지 문제 가있을 수 있습니다 .


5
여전히 똑같은 모듈을 사용해야하는데 두 가지 다른 버전을 사용해야한다면 어떨까요? 동일한 클래스의 두 가지 버전이 공존 할 수 있도록 일종의 지원을 추가해야하지 않습니까?
Didier A.

7
이 게시물은 실제로 Java 9에서 릴리스 될 예정인 내용을 감안할 때 오해의 소지가 있습니다. 작성 당시에는 정확했을 수 있습니다.
xenoterracide

1
mreinhold.org/blog/jigsaw-complete 프로젝트 완료 및 Java 9 출시
Zasz

@xenoterracide, 당신은 투시력이 아니라고 누군가를 탓할 수 없습니다. 이 게시물은 Java 9보다 5 년 앞서 있습니다. Jon Skeet의 모든 답변도 검토하고 있습니까?
duffymo

이 게시물은 잘 숙성되지 않았습니다. Java 모듈은 의도적으로 버전 관리 문제를 해결하지 못합니다 . 이 스레드를 참조하십시오 . 우리의 옛 친구를 해결하기 위해 쉬운 방법 아직 없다 NoSuchMethodError하고 NoClassDefFoundError.
Tamas Hegedus

45

AFAIK 계획은 JRE를 더 모듈화하는 것입니다. 즉, 선택 사항 인 작은 jar가 있으며 필요한 기능 만 다운로드 / 업그레이드 할 수 있습니다.

덜 부풀게 만들고 아마도 대부분의 사람들이 사용하지 않는 레거시 모듈을 삭제할 수있는 옵션을 제공합니다.


7
허용되는 답변은 유효하지만 실제 원하는 효과를 설명하기 때문에이 답변이 더 좋습니다. +1, 당연합니다.
Silviu Burcea 2014 년

나는 이것이 Google Guava를 종속성으로 가지고 있지만 ImmutableList 만 사용하는 경우 ImmutableList 종속성 만 가져오고 나머지 Guava 클래스는 제외시킬 수 있다는 것을 의미합니까?
tmn

1
@ThomasN. 를 사용할 때이 import모든 작업은 컴파일러의 클래스 이름 공간에이 클래스를 도입하는 것입니다. 실제로 사용하지 않으면 생성 된 바이트 코드에 표시되지 않습니다. 실제로 클래스를 사용하는 경우 해당 클래스와 런타임에 사용하는 모든 클래스가 있어야합니다. 이론적으로는 필요한 것만 포함하고 대신 해당 JAR을 사용하는 구아바 API의 축소 버전을 만들 수 있습니다. 실제로 이것은 오류가 발생하기 쉽고 대부분의 경우 유용하지 않으며 릴리스 된대로 전체 JAR을 추가하게됩니다.
Peter Lawrey 2015 년

43

를 기반으로 마크 라인 홀드Devoxx 벨기에에서 기조 연설 , 프로젝트 직소은 주소 두 가지 고통 포인트 것입니다 :

  1. 클래스 경로
  2. 대규모 모 놀리 식 JDK

Classpath의 문제점은 무엇입니까?

우리 모두는 JAR 지옥 에 대해 알고 있습니다. 이 용어는 클래스 로딩 프로세스가 작동하지 않을 수 있는 모든 다양한 방법을 설명합니다 . 클래스 경로의 가장 알려진 제한 사항은 다음과 같습니다.

  • 갈등이 있는지 말하기 어렵습니다. maven과 같은 빌드 도구는 아티팩트 이름을 기반으로 꽤 좋은 작업을 수행 할 수 있지만 아티팩트 자체의 이름은 다르지만 내용은 같으면 충돌이 발생할 수 있습니다.
  • jar 파일의 근본적인 문제는 구성 요소가 아니라는 것입니다. 선형으로 검색되는 파일 컨테이너의 무리입니다. Classpath는 어떤 구성 요소에 있는지, 어떤 패키지에 있는지 또는 의도 된 용도에 관계없이 클래스를 조회하는 방법입니다.

대규모 모 놀리 식 JDK

JDK의 큰 모 놀리 식 특성으로 인해 몇 가지 문제가 발생합니다.

  • 작은 장치에는 맞지 않습니다. 작은 IoT 유형 장치에는 SE 클래스 VM을 실행할 수있는 프로세서가 있지만 모든 JDK를 저장할 메모리가 반드시 필요한 것은 아닙니다. 특히 응용 프로그램이 일부만 사용하는 경우에는 더욱 그렇습니다.
  • 클라우드에서도 문제가됩니다. 클라우드는 하드웨어 사용을 최적화하는 것입니다. 전체 JDK를 포함하는 수천 개의 이미지를 얻었지만 애플리케이션이 그 중 일부만 사용한다면 낭비가 될 것입니다.

모듈 : 공통 솔루션

위의 문제를 해결하기 위해 우리는 모듈을 근본적인 새로운 종류의 Java 프로그램 구성 요소로 취급합니다. 모듈은 명명 된 자체 설명 코드 및 데이터 모음입니다. 코드는 유형, 즉 Java 클래스 및 인터페이스를 포함하는 패키지 세트로 구성됩니다. 데이터에는 리소스 및 기타 종류의 정적 정보가 포함됩니다.

코드가 다른 모듈의 유형을 참조하는 방식을 제어하기 위해 모듈은 컴파일 및 실행에 필요한 다른 모듈을 선언합니다. 다른 모듈의 코드가 패키지의 유형을 참조하는 방법을 제어하기 위해 모듈은 내보낼 패키지를 선언합니다.

모듈 시스템은 필요한 모듈을 찾고 클래스 경로 메커니즘과 달리 모듈의 코드가 종속 된 모듈의 유형 만 참조 할 수 있도록합니다. Java 언어 및 Java 가상 머신의 액세스 제어 메커니즘은 정의 모듈에서 내 보내지 않은 패키지의 유형에 코드가 액세스하는 것을 방지합니다.

더 안정적인 것 외에도 모듈화는 성능을 향상시킬 수 있습니다. 모듈의 코드가 패키지의 유형을 참조 할 때 해당 패키지는 해당 모듈 또는 해당 모듈에서 읽은 모듈 중 정확히 하나에서 정의됩니다. 따라서 특정 유형의 정의를 찾을 때 여러 모듈에서 또는 전체 클래스 경로를 따라 검색 할 필요가 없습니다.

따라야 할 JEP

Jigsaw는 꽤 오랫동안 진행되고있는 거대한 프로젝트입니다. 프로젝트에 대한 더 많은 정보를 얻을 수있는 훌륭한 장소 인 인상적인 양의 JEP가 있습니다. 이러한 JEP 중 일부는 다음과 같습니다.

  • JEP 200 : 모듈 식 JDK : JPMS (Java Platform Module System)를 사용하여 JDK 모듈화
  • JEP 201 : 모듈 식 소스 코드 : JDK 소스 코드를 모듈로 재구성하고, 빌드 시스템을 강화하여 모듈을 컴파일하고, 빌드시 모듈 경계를 적용합니다.
  • JEP 261 : 모듈 시스템 : 관련 JDK 관련 변경 및 개선 사항과 함께 JSR 376에 지정된대로 Java 플랫폼 모듈 시스템을 구현합니다 .
  • JEP 220 : 모듈 식 런타임 이미지 : 모듈을 수용하고 성능, 보안 및 유지 보수성을 향상시키기 위해 JDK 및 JRE 런타임 이미지를 재구성합니다 .
  • JEP 260 : 대부분의 내부 API 캡슐화 : 기본적으로 JDK의 내부 API 대부분을 액세스 할 수 없게하지만 기능의 전부 또는 대부분에 대해 지원되는 대체가 존재할 때까지 널리 사용되는 몇 가지 중요하고 널리 사용되는 내부 API에 액세스 할 수 있습니다.
  • JEP 282 : jlink : Java Linker : JEP 220에 정의 된대로 모듈 세트와 해당 종속성을 사용자 지정 런타임 이미지로 조합하고 최적화 할 수있는 도구를 만듭니다.

맺음말

The State of the Module System 보고서 초판 에서 Mark Reinhold는 모듈 시스템의 구체적인 목표를 다음과 같이 설명합니다.

  • 불안정하고 오류가 발생하기 쉬운 클래스 경로 메커니즘을 프로그램 구성 요소가 서로에 대한 명시 적 종속성을 선언하는 수단으로 대체하기위한 안정적인 구성
  • 강력한 캡슐화- 구성 요소가 다른 구성 요소에 액세스 할 수있는 공용 유형과 그렇지 않은 유형을 선언 할 수 있도록합니다.

이러한 기능은 응용 프로그램 개발자, 라이브러리 개발자 및 Java SE 플랫폼 자체 구현 자에게 직접적으로 그리고 간접적으로도 도움이 될 것입니다. 확장 가능한 플랫폼, 더 큰 플랫폼 무결성 및 향상된 성능을 가능하게하기 때문입니다.


3
Mark Reinhold는 Oracle Java Platform Group의 수석 아키텍트이며이 대답은 본질적으로 정확한 질문에 대한 그의 직접적인 대답입니다.
Jay

1
이를 수량화하기 위해 HelloWorld는 553MB 대신 15MB를 사용할 수 있습니다. youtu.be/rFhhLXcOBsk?t=31m12s
user1133275 '172017-08-30

14

논쟁을 위해 Java 8 (및 이전 버전)에 이미 모듈 (jars) 및 모듈 시스템 (클래스 경로)의 "형식" 있다고 가정 해 보겠습니다 . 그러나 이것들에는 잘 알려진 문제가 있습니다.

문제를 조사하여 Jigsaw의 동기를 설명 할 수 있습니다. (다음은 확실히 솔루션을 제공하는 OSGi, JBoss 모듈 등을 사용하지 않는다고 가정합니다.)

문제 1 : 공개가 너무 공개적입니다

다음 클래스를 고려하십시오 (둘 다 공용이라고 가정).

com.acme.foo.db.api.UserDao
com.acme.foo.db.impl.UserDaoImpl

Foo.com에서, 우리는 우리의 팀이 사용하도록 결정할 수 있습니다 UserDao사용하지UserDaoImpl 직접 있습니다. 그러나 클래스 경로에 적용 할 수있는 방법은 없습니다.

Jigsaw에서 모듈에는 module-info.java다른 모듈에 공개 된 내용을 명시 적으로 지정할 수 있는 파일이 포함되어 있습니다 . 즉, 대중에는 뉘앙스가 있습니다. 예를 들면 :

// com.acme.foo.db.api.UserDao is accessible, but
// com.acme.foo.db.impl.UserDaoImpl is not 
module com.acme.foo.db {
    exports com.acme.foo.db.api;
}

문제 2 : 반성이 자유 롭다

# 1의 클래스를 감안할 때 누군가 Java 8에서 여전히이 작업을 수행 할 수 있습니다.

Class c = Class.forName("com.acme.foo.db.impl.UserDaoImpl");
Object obj = c.getConstructor().newInstance();

즉, 리플렉션은 강력하고 필수적이지만 선택하지 않으면 바람직하지 않은 방식으로 모듈의 내부에 도달하는 데 사용될 수 있습니다. Mark Reinhold는 다소 놀라운 예가 있습니다. (SO 포스트는 여기에 있습니다 .)

Jigsaw에서 강력한 캡슐화 는 리플렉션을 포함하여 클래스에 대한 액세스를 거부하는 기능을 제공합니다. (이는 JDK 9에 대한 수정 된 기술 사양을 기다리는 동안 명령 줄 설정에 따라 달라질 수 있습니다.) JDK 자체에 Jigsaw가 사용되기 때문에 Oracle은 이것이 Java 팀이 플랫폼 내부를 더 빠르게 혁신 할 수 있도록 할 것이라고 주장합니다.

문제 3 : 클래스 경로가 아키텍처 관계를 지 웁니다.

팀은 일반적으로 항아리 간의 관계에 대한 정신 모델을 가지고 있습니다. 예를 들어, foo-app.jar사용할 수 foo-services.jar있는 용도 foo-db.jar. 의 클래스는 foo-app.jar"서비스 계층"을 우회하여 foo-db.jar직접 사용해서는 안된다고 주장 할 수 있습니다. 그러나 클래스 경로를 통해이를 강제하는 방법은 없습니다. Mark Reinhold는 여기에서 이것을 언급 합니다 .

이에 비해 Jigsaw는 모듈에 대해 명시적이고 신뢰할 수있는 접근성 모델을 제공합니다.

문제 4 : 모 놀리 식 런타임

자바 런타임은 모 놀리 식 rt.jar. 내 컴퓨터에서는 20k 클래스로 60MB 이상입니다! 마이크로 서비스, IoT 장치 등의 시대에 Corba, Swing, XML 및 기타 라이브러리를 사용하지 않는 경우 디스크에 두는 것은 바람직하지 않습니다.

Jigsaw는 JDK 자체 를 여러 모듈로 나눕니다 . 예를 들어 java.sql 에는 익숙한 SQL 클래스가 포함되어 있습니다. 여기에는 몇 가지 이점이 있지만 새로운 것이 jlink도구입니다. 앱이 완전히 모듈화되었다고 가정하고 지정된 모듈 (및 해당 종속성) 만 포함하도록 잘린 배포 가능한 런타임 이미지jlink생성합니다 . 오라클 JDK 모듈이 사전에 네이티브 코드로 컴파일 되는 미래를 구상하고 있습니다 . 비록 선택 사항이며, AOT 컴파일 실험, 그들은 오라클이 향하고 곳의 주요 징후이다.jlink

문제 5 : 버전 관리

예 :이 클래스 패스는 우리가 여러 같은 항아리의 버전을 사용하는 것을 허용하지 않는다는 것을 잘 알려져있다 bar-lib-1.1.jarbar-lib-2.2.jar.

Jigsaw는이 문제를 해결하지 않습니다. Mark Reinhold는 여기근거를 설명합니다 . 요점은 Maven, Gradle 및 기타 도구가 종속성 관리를위한 대규모 생태계를 나타내며 다른 솔루션이 유익하기보다는 더 해롭다는 것입니다.

다른 솔루션 (예 : OSGi)은 실제로이 문제를 해결합니다 (4 번을 제외한 다른 솔루션).

결론

이것은 특정 문제에 의해 동기가 부여 된 Jigsaw의 핵심 포인트입니다.

Jigsaw, OSGi, JBoss 모듈 등 간의 논쟁을 설명하는 것은 다른 Stack Exchange 사이트에 속하는 별도의 토론입니다. 여기에 설명 된 것보다 솔루션간에 더 많은 차이점이 있습니다. 또한 JSR 376에 대한 공개 검토 재검토 투표 를 승인하기에 충분한 합의가있었습니다 .


3

이 기사에서는 OSGi와 JPMS / Jigsaw가 해결하려는 문제를 자세히 설명합니다.

"Java 9, OSGi 및 모듈성의 미래" [2016 년 9 월 22 일]

또한 OSGi 및 JPMS / Jigsaw의 접근 방식에 대해 철저하게 설명합니다. 현재 저자들은 성숙한 (16 세) OSGi에 비해 JPMS / Jigsaw에 대한 실질적인 프로를 거의 나열하지 않은 것으로 보입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.