85
Alexis Hassler Le classpath n'est pas mort... MarsJUG septembre 2013 mais presque

MarsJUG - Le classpath n'est pas mort, mais presque

Embed Size (px)

DESCRIPTION

En 2009, la mort du classpath a été annoncée. Les classloaders à plat ou hiérarchiques devaient être remplacés par des systèmes modulaires et tous nos problèmes de dépendances devaient se résoudre d'eux-même. Quatre ans plus tard, le classpath vit toujours et pour quelques années encore. Dans la première partie de cette session, nous reviendrons sur le fonctionnement des classloaders du JDK et les problèmes infernaux posés par le classpath. Nous verrons aussi comment les serveurs d'applications, comme Tomcat, gèrent leur classloaders de façon hiérarchique, afin d'isoler les applications entre elles. Dans la deuxième partie, nous parlerons de modularité et de son impact sur la gestion des dépendances, à l'exécution des applications. Des solutions existent déjà, comme OSGi et Jigsaw, d'autres émergent, comme JBoss Modules. Nous vous montrerons comment ce dernier fonctionne, dans JBoss AS 7, en autonome, ou même dans Tomcat.

Citation preview

Page 1: MarsJUG - Le classpath n'est pas mort, mais presque

Alexis Hassler

Le classpath n'est pas mort...

MarsJUGseptembre 2013

mais presque

Page 2: MarsJUG - Le classpath n'est pas mort, mais presque

"Class�path is dead!"

Mark Reinhold

JavaOne 2009

Page 3: MarsJUG - Le classpath n'est pas mort, mais presque

Classpath

Page 4: MarsJUG - Le classpath n'est pas mort, mais presque

Classloader

Page 5: MarsJUG - Le classpath n'est pas mort, mais presque

Mort ?

Page 6: MarsJUG - Le classpath n'est pas mort, mais presque

Successeur

Page 7: MarsJUG - Le classpath n'est pas mort, mais presque

Alexis Hassler

Développeur, formateur Java

Indépendant

Co-leader du

Page 8: MarsJUG - Le classpath n'est pas mort, mais presque

Classpath

Page 9: MarsJUG - Le classpath n'est pas mort, mais presque

Chercher les classes

String hello = "Bonjour Devoxx";

MyStuff var;

CLASSPATH

Page 10: MarsJUG - Le classpath n'est pas mort, mais presque

-classpath

java -cp hello-lib.jar HelloWorld

Page 11: MarsJUG - Le classpath n'est pas mort, mais presque

Manifest

Manifest-Version: 1.0

Class-Path: hello-lib.jar

Main-Class: HelloWorld

Page 12: MarsJUG - Le classpath n'est pas mort, mais presque

Connaitre le classpath

System.getProperty("java.class.path");

Page 13: MarsJUG - Le classpath n'est pas mort, mais presque

Erreurs

java.lang.NoClassDefFoundError

java.lang.ClassNotFoundException

Page 14: MarsJUG - Le classpath n'est pas mort, mais presque

Classpath

Géré par des classloaders

Page 15: MarsJUG - Le classpath n'est pas mort, mais presque

Classloader

Page 16: MarsJUG - Le classpath n'est pas mort, mais presque

java.lang.ClassLoader

loadClass(String name) : Class<?>

getResource(String name) : URLgetResources(String name) : Enumeration<URL>getResourceAsStream(String name) : InputStream

getParent() : ClassLoader

Page 17: MarsJUG - Le classpath n'est pas mort, mais presque

Classloader

MyStuff.class.getClassLoader()

sun.misc.Launcher$AppClassLoader

CLASSPATH

Page 18: MarsJUG - Le classpath n'est pas mort, mais presque

Bootstrap Classloader

classloader.getClass().getClassLoader()

null

Page 19: MarsJUG - Le classpath n'est pas mort, mais presque

Bootstrap Classloader

BootstrapClassLoader

Page 20: MarsJUG - Le classpath n'est pas mort, mais presque

ExtensionCl

asspath

sun.misc.Launcher$ExtClassLoader

sun.misc.Launcher$AppClassLoader

Délégation

BootstrapClassLoader

Parent first

Parent first

System ClassLoader

Extension ClassLoader

Page 21: MarsJUG - Le classpath n'est pas mort, mais presque

Délégation

java -cp hello-lib.jar ...

System.getProperty("java.class.path");

ClasspathSystem ClassLoader

Page 22: MarsJUG - Le classpath n'est pas mort, mais presque

Délégation

java -Djava.ext.dirs=~/.java7/ext ...

System.getProperty("java.ext.dirs");

Extension

Extension ClassLoader

Page 23: MarsJUG - Le classpath n'est pas mort, mais presque

Délégation

Ext != Endorsed

Page 24: MarsJUG - Le classpath n'est pas mort, mais presque

Délégation

java -Xbootclasspath:hello-rt.jar ...

BootstrapClassLoader

System.getProperty("sun.boot.class.path");

Page 25: MarsJUG - Le classpath n'est pas mort, mais presque

bootclasspath

●java -Xbootclasspath:hello-rt.jar ...

●java -Xbootclasspath/a:hello-lib.jar ...

●java -Xbootclasspath/p:hello-lib.jar ...

Page 26: MarsJUG - Le classpath n'est pas mort, mais presque

Endorsed

java -Djava.endorsed.dirs=~/.java7/endorsed ...

Endorsed

BootstrapClassLoader

Page 27: MarsJUG - Le classpath n'est pas mort, mais presque

Endorsed

APIs standards hors JCPorg.omg (CORBA), org.w3c.dom, org.xml.sax (XML)

APIs standaloneJAXP, JAXB, Scripting, Compiler API,...

Page 28: MarsJUG - Le classpath n'est pas mort, mais presque

27 au 29 mars 2013

Démonstration

http://github.com/hasalex/classpath-demo

Page 29: MarsJUG - Le classpath n'est pas mort, mais presque

classloader-demo

DémonstrationBootstrapClassLoaderSystem ClassLoader

java -cp cl-demo.jar fr.sewatech.classpath.Count

Page 30: MarsJUG - Le classpath n'est pas mort, mais presque

classloader-demo

DémonstrationBootstrapClassLoader

java -Xbootclasspath/p:lib/cl-demo.jar fr.sewatech.classpath.Count

Page 31: MarsJUG - Le classpath n'est pas mort, mais presque

URLClassloader

java.net.URLClassLoader

sun.misc.Launcher$AppClassLoader

sun.misc.Launcher$ExtClassLoader

URLURLURL

Page 32: MarsJUG - Le classpath n'est pas mort, mais presque

URLClassloader

System ClassLoader

Bootstrap ClassLoader

URL ClassLoader

URL ClassLoader

URL ClassLoader

Parent first

Parent first

Parent first

Page 33: MarsJUG - Le classpath n'est pas mort, mais presque

FLTM Classloader

Fait Le Toi-Même

Page 34: MarsJUG - Le classpath n'est pas mort, mais presque

Usages

Application ServersJRebel

Javassist, CGLib,...

Page 35: MarsJUG - Le classpath n'est pas mort, mais presque

Tomcat

System

Bootstrap

Common

Webapp1

Webapp2

Webapp3

Local First

Page 36: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss AS 5

System

Bootstrap

Common

Web App

Ent App

Web Module

EJB Module

Local First

Repo First

Page 37: MarsJUG - Le classpath n'est pas mort, mais presque

Erreurs

ClassCastExceptionMyStuff cannot be cast to MyStuff

WTF ?

Page 38: MarsJUG - Le classpath n'est pas mort, mais presque

Erreurs

URL ClassLoader

URL ClassLoader

MyStuff var = MyStuffFactory.build();

return new MyStuff() ;

Page 39: MarsJUG - Le classpath n'est pas mort, mais presque

27 au 29 mars 2013

Démonstration

http://github.com/hasalex/classpath-demo

Page 40: MarsJUG - Le classpath n'est pas mort, mais presque

classloader-demo

message-main

message-common

Démonstration

message-printer

Page 41: MarsJUG - Le classpath n'est pas mort, mais presque

classloader-demo

message-main

message-common

Démonstration

message-printer

java -cp cl-demo.jar:msg-main.jar fr.sewatech.classpath.HelloViaMvnRepo

Page 42: MarsJUG - Le classpath n'est pas mort, mais presque

Démonstration

java -cp cl-demo.jar:msg-main.jar fr.sewatech.classpath.HelloViaMvnRepo

classloader-demo

message-main

message-common

message-printer

message-main

Classpa

thMaven

Reposito

ry

ClassL

oader

Page 43: MarsJUG - Le classpath n'est pas mort, mais presque

Démonstration

classloader-demo

message-common

message-printer

message-main

message-main

System ClassLoader ParentFirst ClassLoader

Page 44: MarsJUG - Le classpath n'est pas mort, mais presque

Démonstration

System ClassLoader LocalFirst ClassLoader

classloader-demo

message-common

message-printer

message-main

message-main

Page 45: MarsJUG - Le classpath n'est pas mort, mais presque

Mort

Page 46: MarsJUG - Le classpath n'est pas mort, mais presque

Jar

HELL

http://www.ironmaidenwallpaper.com/

Page 47: MarsJUG - Le classpath n'est pas mort, mais presque

Dépendances

Maven, Gradle,...

Page 48: MarsJUG - Le classpath n'est pas mort, mais presque

Dépendances

Classpath

Page 49: MarsJUG - Le classpath n'est pas mort, mais presque

Runtime

A plat

Fichiers jarjuste du stockagepas ou peu de métadonnée

Classpath

Page 50: MarsJUG - Le classpath n'est pas mort, mais presque

Runtime

Hiérarchique applications server

Page 51: MarsJUG - Le classpath n'est pas mort, mais presque

27 au 29 mars 2013

Démonstration

http://github.com/hasalex/classpath-demo

Page 52: MarsJUG - Le classpath n'est pas mort, mais presque

message-main

message-common

Démonstration

message-printer

classloader-demo

slf4j-api 1.5.11

slf4j-api 1.7.2

Page 53: MarsJUG - Le classpath n'est pas mort, mais presque

Remplaçant

Page 54: MarsJUG - Le classpath n'est pas mort, mais presque

Application

Granularité

Classpath

Page 55: MarsJUG - Le classpath n'est pas mort, mais presque

Application Monolithique

Granularité

Application Web / JavaEE

Page 56: MarsJUG - Le classpath n'est pas mort, mais presque

Librairies partagéesApplication

Granularité

Application Web / JavaEE

Page 57: MarsJUG - Le classpath n'est pas mort, mais presque

Application

Modularité

Application Web / JavaEE

Page 58: MarsJUG - Le classpath n'est pas mort, mais presque

Modularité

Visibilité

Import

Export

Dépendancestransitives

Page 59: MarsJUG - Le classpath n'est pas mort, mais presque

1999

Java embarquéJava SEJava serveur

Page 60: MarsJUG - Le classpath n'est pas mort, mais presque

OSGi

BundleFichier jarMETA-INF/MANIFEST.MFImport / export de packages

Page 61: MarsJUG - Le classpath n'est pas mort, mais presque

Bundle-Name = Simple Bundle

Bundle-SymbolicName = simple-bundle

Bundle-Description = Simple Bundle.

Export-Package = fr.sewatech.mystuff.services

Import-Package = org.osgi.framework;version=1.3

Bundle-Version = 1.0.1

OSGi

Page 62: MarsJUG - Le classpath n'est pas mort, mais presque

OSGi

OS + Hardware

Java Execution Environment

Applications(bundles)

Module

Life Cycle

Services

Page 63: MarsJUG - Le classpath n'est pas mort, mais presque

OSGi

Apporte de la valeur=> applications hautement dynamiques

Apporte de la complexité=> outils pour gérer la complexité

Page 64: MarsJUG - Le classpath n'est pas mort, mais presque

Jigsaw

Projet OpenJDK

Intégré au JDK 7

9 (2016)

8 (2012)

(2008)

. . .

Page 65: MarsJUG - Le classpath n'est pas mort, mais presque

Jigsaw

Modularité des applications

Modularité du JDK

Page 66: MarsJUG - Le classpath n'est pas mort, mais presque

Jigsaw

Dépendance à une partie du JDKPlus besoin de Corba pour Hello WorldPlus besoin de Swing pour Tomcat

RepositoryTéléchargement automatique des modules

Page 67: MarsJUG - Le classpath n'est pas mort, mais presque

Jigsaw

module-info.java

module message-main @ 1.0 {

exports fr.sewatech.message;

requires fr.sewatech.message-common @ 1.1;

class fr.sewatech.message.Main;

}

Page 68: MarsJUG - Le classpath n'est pas mort, mais presque
Page 69: MarsJUG - Le classpath n'est pas mort, mais presque
Page 70: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss Modules

Sous-projet de JBoss AS 7

Inspiré de Jigsaw

Base de JBoss OSGi

Page 71: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss Modules

java -jar jboss-modules.jar -mp path/to/modules

my.main.module.name

Java SE

Page 72: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss Modules

hibernate-infinispan-4.1.6.Final.jar

module.xml

hibernate-core-4.1.6.Final.jar

hibernate-entitymanager-4.1.6.Final.jar

modules

com

fr

org

...

org

hibernate

main

Page 73: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss Modules

<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.1"

name="fr.sewatech.conference.classloader-demo">

<main-class name="fr.sewatech.classpath.Hello"/>

<resources>

<resource-root path="classloader-demo-1.0-SNAPSHOT.jar"/>

</resources>

<dependencies>

<module name="fr.sewatech.conference.message-main" />

</dependencies>

</module>

Page 74: MarsJUG - Le classpath n'est pas mort, mais presque

<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.1" name="org.hibernate">

<resources>

<resource-root path="hibernate-core-4.0.0.Final.jar"/>

<resource-root path="hibernate-commons-annotations-4.0.1.Final.jar"/>

<resource-root path="hibernate-entitymanager-4.0.0.Final.jar"/>

</resources>

<dependencies>

<module name="javax.api"/>

<module name="javax.persistence.api"/>

<module name="javax.transaction.api"/>

<module name="org.apache.commons.collections"/>

<!-- ... -->

</dependencies>

</module>

Page 75: MarsJUG - Le classpath n'est pas mort, mais presque

27 au 29 mars 2013

Démonstration

http://github.com/hasalex/classpath-demo

Page 76: MarsJUG - Le classpath n'est pas mort, mais presque

JBoss AS 7

bin Scripts de démarrage

bundles Composants OSGi

modules Modules JBoss

standalone Profil standalone

domain Profil domain

Page 77: MarsJUG - Le classpath n'est pas mort, mais presque

bin Scripts de démarrage

bundles Composants OSGi

modules Modules JBoss

standalone Profil standalone

domain Profil domain

JBoss AS 7

message.war

Page 78: MarsJUG - Le classpath n'est pas mort, mais presque

Tomcat

WEB-INF/classes, WEB-INF/lib

System ClassLoader

CommonClass Loader

WebappClassLoader

$CATALINA_HOME/lib

Classloading

Page 79: MarsJUG - Le classpath n'est pas mort, mais presque

Tomcat

WEB-INF/classes, WEB-INF/lib

System ClassLoader

CommonClass Loader

WebappClassLoader

$CATALINA_HOME/lib

Module ?

ModuleClassLoader

modules

Page 80: MarsJUG - Le classpath n'est pas mort, mais presque

Tomcat

A suivre...

https://github.com/hasalex/tomcat-modules

Page 81: MarsJUG - Le classpath n'est pas mort, mais presque

27 au 29 mars 2013

Démonstration

http://github.com/hasalex/classpath-demo

Page 82: MarsJUG - Le classpath n'est pas mort, mais presque

Cible

Applications complexes

Beaucoup de réutilisation

Page 83: MarsJUG - Le classpath n'est pas mort, mais presque

Développement / déploiement

Artefacts ≠ ModulesNotions différentesOutillage difficile

Page 84: MarsJUG - Le classpath n'est pas mort, mais presque

En attendant Jigsaw ?

Page 85: MarsJUG - Le classpath n'est pas mort, mais presque

Merci