2017幎ã«1ã€ã®ã©ã€ãã©ãªã®è€æ°ã®ããŒãžã§ã³ã§Javaã¢ããªã±ãŒã·ã§ã³ãå®è¡ããæ¹æ³
ç§ãçŽé¢ããªããã°ãªããªãã£ã1ã€ã®åé¡ã®è§£æ±ºçãšãJava 9ã®ã³ã³ããã¹ãã§ã®ãã®åé¡ã®èª¿æ»ãå
±æããããšæããŸãã
å
責äºé
ç§ã®äœå®¶ã¯ãŸã ã§ãïŒç§ã¯åããŠæžããŠããŸãïŒã®ã§ãæããŸã ãããã çç±ã瀺ããããã¯å€§æè¿ã§ãã
èšäºã以äžã®ã¬ã€ããšããŠé©åã§ã¯ãªãããšã«çŽã¡ã«åæããŸãã
- Java 9
- Elasticsearch
- ã¡ã€ãŽã³
ãããã¯ãŒã¯å
ã®æ
å ±ã®å§ããã£ã±ãã®å Žåãæåã«...ã衚瀺ãããŸã ãå°ãªããšãå¿
èŠãªæ
å ±ããããŸãã
åçŽãªç¶æ³ãæ³åããŠãã ãããElasticsearchã¯ã©ã¹ã¿ãŒããããã€ããããã«ããŒã¿ãããŒãããŸãã ãã®ã¯ã©ã¹ã¿ãŒãæ€çŽ¢ããã¢ããªã±ãŒã·ã§ã³ãäœæããŠããŸãã Elasticsearchã®æ°ããããŒãžã§ã³ã絶ãããªãªãŒã¹ãããŠãããããæ°ããããŒãžã§ã³ãã¯ã©ã¹ã¿ãŒã«å°å
¥ããŸã åé¡ ããŒãªã³ã°ã¢ããã°ã¬ãŒãã䜿çšããæ©èœã ããããããã«åé¡ããããŸã-ããæç¹ã§ãä¿åãããããŒã¿ã®åœ¢åŒãå€æŽãïŒããšãã°ãæ°ããæ©èœã®1ã€ãæ倧éã«æŽ»çšããããïŒãã€ã³ããã¯ã¹ã®åäœæãäžé©åã«ããŸããã ãã®ãªãã·ã§ã³ã¯ç§ãã¡ã«é©ããŠããŸãïŒåããã·ã³ã«æ°ããã¯ã©ã¹ã¿ãŒãã€ã³ã¹ããŒã«ããŸã-å€ãããŒã¿ã¹ããŒã ãæã€æåã®ã¯ã©ã¹ã¿ãŒã¯æ€çŽ¢ã®ããã ãã«æ®ããæ°ããããŒã¿ã¹ããŒã ãæã€åä¿¡ããŒã¿ã¯2çªç®ã«ããŒããããŸãã 次ã«ãæ€çŽ¢ã³ã³ããŒãã³ãã¯2ã€ã®ã¯ã©ã¹ã¿ãŒã«æ¥ç¶ããå¿
èŠããããŸãã
ãã®ã¢ããªã±ãŒã·ã§ã³ã¯Java APIã䜿çšããŠã¯ã©ã¹ã¿ãŒãšéä¿¡ããŸããã€ãŸããElasticsearchèªäœãäŸåé¢ä¿ã«ãã«ããŸãã 5çªç®ã®ããŒãžã§ã³ãšãšãã«Rest ClientããªãªãŒã¹ãããããšã§ããã®ãããªåé¡ïŒElasticsearchã®äŸ¿å©ãªAPIãããïŒãç¯çŽã§ããããšã¯æ³šç®ã«å€ããŸããã2çªç®ã®ããŒãžã§ã³ã®ãªãªãŒã¹æã«å¯Ÿå¿ããäºå®ã§ãã
Elasticsearch 1.7ããã³2.4ã®2ã€ã®ã¯ã©ã¹ã¿ãŒã§ããã¥ã¡ã³ããæ€çŽ¢ãããšããåçŽãªã¢ããªã±ãŒã·ã§ã³ã®äŸã䜿çšããŠãå¯èœãªè§£æ±ºçãèããŠã¿ãŸãããã ã³ãŒãã¯githubã§å
¥æã§ãããã®èšäºã®æ§é ãç¹°ãè¿ããŸãïŒOSGiã®ã¿ãæ¬ èœããŠããŸãïŒã
ããžãã¹ã«åãæãããã 次ã®æ§é ãæã€Mavenãããžã§ã¯ããäœæããŸãã
+---pom.xml +---core/ | +---pom.xml | +---src/ | +---main/ | | +---java/ | | | +---elasticsearch/ | | | +---client/ | | | +---SearchClient.java | | | +---Searcher.java | | +---resources/ | +---test/ | +---java/ +---es-v1/ | +---pom.xml | +---src/ | +---main/ | | +---java/ | | | +---elasticsearch/ | | | +---client/ | | | +---v1/ | | | +---SearchClientImpl.java | | +---resources/ | +---test/ | +---java/ +---es-v2/ +---pom.xml +---src/ +---main/ | +---java/ | | +---elasticsearch/ | | +---client/ | | +---v2/ | | +---SearchClientImpl.java | +---resources/ +---test/ +---java/
æããã«ã1ã€ã®ã¢ãžã¥ãŒã«ã§åãã©ã€ãã©ãªã®è€æ°ã®ããŒãžã§ã³ãæ¥ç¶ããŠãæ©èœããªãããããããžã§ã¯ãã¯ãã«ãã¢ãžã¥ãŒã«ã§ããå¿
èŠããããŸãã
- ã³ã¢ -ãããã¢ããªã±ãŒã·ã§ã³ã®ããžãã¯å
šäœã§ãã
- Elasticsearchãšã®å¯Ÿè©±çšã®ã€ã³ã¿ãŒãã§ã€ã¹ãå¥ã®ã¢ãžã¥ãŒã«ã«è»¢éããããšãã§ããŸãïŒãããŠå¿
èŠã§ãïŒã
- es-v1 -Elasticsearch 1.7.5ã®ã€ã³ã¿ãŒãã§ãŒã¹å®è£
ã
- es-v2 -Elasticsearch 2.4.5ã®ã€ã³ã¿ãŒãã§ãŒã¹å®è£
ã
ã³ã¢ã¢ãžã¥ãŒã«ã«ã¯ã es-v1ããã³es-v2ã¢ãžã¥ãŒã«ã®ããã¹ããã§ããSearcher
ã¯ã©ã¹ãå«ãŸããŠããŸãã
public class Searcher { public static void main(String[] args) throws Exception { List<SearchClient> clients = Arrays.asList( getClient("1"), getClient("2") ); for (SearchClient client : clients) { System.out.printf("Client for version: %s%n", client.getVersion()); Map doc = client.search("test"); System.out.println("Found doc:"); System.out.println(doc); System.out.println(); } clients.forEach(SearchClient::close); } private static SearchClient getClient(String desiredVersion) throws Exception { return null;
è¶
èªç¶çãªããšã¯äœããããŸãããã¢ãžã¥ãŒã«ã§äœ¿çšãããElasticsearchã®ããŒãžã§ã³ã衚瀺ããããããä»ãããã¹ãæ€çŽ¢ãå®è¡ãããŸã-ããã§ååã§ãã
å®è£
ã®1ã€ãèŠãŠã¿ãŸãããã2ã€ç®ã¯ã»ãšãã©åãã§ãã
public class SearchClientImpl implements SearchClient { private final Settings settings = ImmutableSettings.builder() .put("cluster.name", "es1") .put("node.name", "es1") .build(); private final Client searchClient = new TransportClient(settings) .addTransportAddress(getAddress()); private InetSocketTransportAddress getAddress() { return new InetSocketTransportAddress("127.0.0.1", 9301); } @Override public String getVersion() { return Version.CURRENT.number(); } @Override public Map search(String term) { SearchResponse response = searchClient.prepareSearch("*") .setQuery(QueryBuilders.termQuery("field", term)) .execute() .actionGet(); if (response.getHits().getTotalHits() > 0) { return response.getHits().getAt(0).getSource(); } else { return null; } } @Override public void close() { searchClient.close(); } }
ãã¹ãŠãç°¡åã§ããçŸåšã®ããŒãžã§ã³ã¯ãElasticsearchã§é
ç·ããããã¹ãŠã®ã€ã³ããã¯ã¹ïŒ *
ïŒã®ãã£ãŒã«ãfield
ã§æ€çŽ¢ãããæåã«èŠã€ãã£ãããã¥ã¡ã³ããããã°ãããè¿ããŸãã
ããã§ã®åé¡ã¯ã Searcher#getClient
ã§SearchClient
ã€ã³ã¿ãŒãã§ã€ã¹ã®SearchClient
ãåŒã³åºããŠãç®çã®çµæãååŸããSearcher#getClient
ã§ãã
ãã¶ãClass.forNameïŒ
ããªããJavaã®å°é家ã§ãªããŠãã ClassLoaderã®ã«ãŒã«ãèããããšãããã¯ãã§ãã ããã©ã«ãã®ãŸãŸã«ãããšãèšç»ãå®äºã§ããªããªããŸãããã®ããããã®ãããªãœãªã¥ãŒã·ã§ã³ã¯æ©èœããŸããã
private static SearchClient getClient(String desiredVersion) throws Exception { String className = String.format("elasticsearch.client.v%s.SearchClientImpl", desiredVersion); return (SearchClient) Class.forName(className).newInstance(); }
åéããå®è¡ããŠçµæã確èªããŸã...ããšãã°ã次ã®ããã«ãããªãäžç¢ºãã§ãã
Exception in thread "main" java.lang.IncompatibleClassChangeError: Implementing class at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:763) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) at java.net.URLClassLoader.access$100(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:368) at java.net.URLClassLoader$1.run(URLClassLoader.java:362) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:361) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at elasticsearch.client.Searcher.getClient(Searcher.java:28) at elasticsearch.client.Searcher.main(Searcher.java:10)
ClassNotFoundException
...ãŸãã¯äœãä»ã®ãã®ãã¹ããŒããå¯èœæ§ããããŸãã...
URLClassLoader
ã¯ãæå®ãããjarãã¡ã€ã«ãšãã£ã¬ã¯ããªã®ã»ããããæå®ãããååãæã€æåã®ã¯ã©ã¹ãèŠã€ããŠããŒããããããããã¯å¿
é ã®ã¯ã©ã¹ã§ã¯ãããŸããã ãã®å Žåã elasticsearch-2.4.5.jar
ãã¯ã©ã¹ãã¹ãªã¹ãå
ã®elasticsearch-1.7.5.jar
elasticsearch-2.4.5.jar
ããããããã®ãšã©ãŒãçºçãããã¹ãŠã®ã¯ã©ã¹ïŒååã§äžèŽããïŒã2.4.5ã§ããŒããããŸãã ã Searcherã¯æåã«Elasticsearch 1.7.5ïŒ getClient("1")
ïŒã®ã¢ãžã¥ãŒã«ãããŒãããããšãããããURLClassLoaderã¯ééã£ãã¯ã©ã¹ãããŒãããŸã...
ã¯ã©ã¹ããŒããŒã®ã¯ã©ã¹ãååïŒããã³ãã¡ã€ã«åïŒã§äº€å·®ããŠããå Žåããã®ç¶æ
ã¯jar hellïŒãŸãã¯class-path hellïŒãšåŒã°ããŸãã
ã«ã¹ã¿ã ClassLoader
ã¢ãžã¥ãŒã«ãšãã®äŸåé¢ä¿ãç°ãªãã¯ã©ã¹ããŒããŒã«åæ£ããå¿
èŠãããããšãæããã«ãªããŸãã es-v *ã¢ãžã¥ãŒã«ããšã«URLClassLoaderãäœæããjarãã¡ã€ã«ã䜿çšããŠåãã£ã¬ã¯ããªã«æå®ããŸãã
private static SearchClient getClient(String desiredVersion) throws Exception { String className = String.format("elasticsearch.client.v%s.SearchClientImpl", desiredVersion); Path moduleDependencies = Paths.get("modules", "es-v" + desiredVersion); URL[] jars = Files.list(moduleDependencies) .map(Path::toUri) .map(Searcher::toURL) .toArray(URL[]::new); ClassLoader classLoader = new URLClassLoader(jars);
ãã¹ãŠã®ã¢ãžã¥ãŒã«ãåéããŠé©åãªmodules/es-v*/
ãã£ã¬ã¯ããªã«ã³ããŒããå¿
èŠããããŸããããã«ã¯ã es-v1ããã³es-v2ã¢ãžã¥ãŒã«ã®maven-dependency-plugin
ã䜿çšããŸãã
ãããžã§ã¯ããçµã¿ç«ãŠãŸãããïŒ
mvn package
ãããŠå®è¡ïŒ
. 29, 2017 10:37:08 org.elasticsearch.plugins.PluginsService <init> INFO: [es1] loaded [], sites [] . 29, 2017 10:37:12 org.elasticsearch.plugins.PluginsService <init> INFO: [es2] modules [], plugins [], sites [] Client for version: 1.7.5 Found doc: {field=test 1} Client for version: 2.4.5 Found doc: {field=test 2}
ãã³ãŽïŒ
ïŒ1.7ã¯JRE 9ã§ã¯æ©èœããŸããïŒElasticsearch 1.7ã®åæ§ç¯ã§åŸè¿°ããããã«ãJvmInfoã«ããããé©çšããªãå Žåã
éåžžã«çéå
¥ãã®ã±ãŒã¹ã§ã¯ã ã³ã¢ã¢ãžã¥ãŒã«ãElasticsearchã©ã€ãã©ãªã®ãŠãŒãã£ãªãã£ã¡ãœããã䜿çšããããšãæ³å®ããŠããŸãã ã¯ã©ã¹ã®ããŒãé åºãåå ã§ãçŸåšã®ãœãªã¥ãŒã·ã§ã³ã¯æ©èœããªããªããŸãã
- findLoadedClassïŒStringïŒãåŒã³åºããŠãã¯ã©ã¹ããã§ã«ããŒããããŠãããã©ããã確èªããŸãã
- 芪ã¯ã©ã¹ããŒããŒã§loadClassã¡ãœãããåŒã³åºããŸãã 芪ãnullã®å Žåã代ããã«ä»®æ³ãã·ã³ã«çµã¿èŸŒãŸããŠããã¯ã©ã¹ããŒããŒã䜿çšãããŸãã
- findClassïŒStringïŒã¡ãœãããåŒã³åºããŠãã¯ã©ã¹ãèŠã€ããŸãã
ã€ãŸãããã®å Žåã es-v *ã§ã¯ãªãã ã³ã¢ã®Elasticsearchã¯ã©ã¹ãããŒããããŸãã ããŒãé åºã詳ããèŠããšãåé¿çããããŸããæé 2ãš3ãéã«ããŠããã®é åºã«éåããã¯ã©ã¹ããŒããŒãäœæããŸãããã®ãããªããŒããŒã¯ã es-v *ã¢ãžã¥ãŒã«ã ãã§ãªãã coreã®ã¯ã©ã¹ãèªã¿èŸŒãããšãã§ããŸãã
URLClassLoaderãäœæããŠãParentLastURLClassLoaderãªã©ã®ååãä»ããŸãããã
public class ParentLastURLClassLoader extends URLClassLoader { ... }
ãããŠloadClass(String,boolean)
ãåå®çŸ©ããClassLoaderããã³ãŒããã³ããŒããäžèŠãªãã®ããã¹ãŠåé€ããŸãã
@Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { Class<?> c = findLoadedClass(name); if (c == null) { try { if (getParent() != null) { c = getParent().loadClass(name); } } catch (ClassNotFoundException e) { } if (c == null) { c = findClass(name); } } if (resolve) { resolveClass(c); } return c; } }
getParent().loadClass(String)
ã findClass(String)
ã®åŒã³åºããå
¥ãæ¿ããŠã次ãååŸããŸãã
@Override protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { Class<?> c = findLoadedClass(name); if (c == null) { try { c = findClass(name); } catch (ClassNotFoundException ignored) { } if (c == null) { c = getParent().loadClass(name); if(c == null) { throw new ClassNotFoundException(name); } } } if (resolve) { resolveClass(c); } return c; } }
ã¢ããªã±ãŒã·ã§ã³ã¯ã¢ãžã¥ãŒã«ã¯ã©ã¹ãæåã§ããŒããããããã¯ã©ã¹ãã©ãã«ãèŠã€ãããªãå ŽåãããŒããŒã¯ClassNotFoundException
ãã¹ããŒããå¿
èŠããããŸãã
ããŒããŒãäœæãããã®ã§ãããã䜿çšããŠã getClient(String)
ã¡ãœããã®URLClassLoader
ã眮ãæããŸãã
ClassLoader classLoader = new URLClassLoader(jars);
ParentLastURLClassLoader
ïŒ
ClassLoader classLoader = new ParentLastClassLoader(jars);
ã¢ããªã±ãŒã·ã§ã³ãå床起åãããšãåãçµæã衚瀺ãããŸãã
. 29, 2017 10:42:41 org.elasticsearch.plugins.PluginsService <init> INFO: [es1] loaded [], sites [] . 29, 2017 10:42:44 org.elasticsearch.plugins.PluginsService <init> INFO: [es2] modules [], plugins [], sites [] Client for version: 1.7.5 Found doc: {field=test 1} Client for version: 2.4.5 Found doc: {field=test 2}
ServiceLoader API
Java 6ã§ã¯ã java.util.ServiceLoaderã¯ã©ã¹ãè¿œå ãããŸãããããã¯ãã€ã³ã¿ãŒãã§ã€ã¹/æœè±¡ã¯ã©ã¹ã«ãã£ãŠå®è£
ãããŒãããã¡ã«ããºã ãæäŸããŸãã ãã®ã¯ã©ã¹ã¯åé¡ã解決ããŸãïŒ
private static SearchClient getClient(String desiredVersion) throws Exception { Path moduleDependencies = Paths.get("modules", "es-v" + desiredVersion); URL[] jars = Files.list(moduleDependencies) .map(Path::toUri) .map(Searcher::toURL) .toArray(URL[]::new); ServiceLoader<SearchClient> serviceLoader = ServiceLoader.load(SearchClient.class, new URLClassLoader(jars)); return serviceLoader.iterator().next(); }
ãã¹ãŠãéåžžã«ç°¡åã§ãïŒ
- ã¢ãžã¥ãŒã«ãã£ã¬ã¯ããªã§ãã¹ãŠã®jarãã¡ã€ã«ãæ¢ããŸãã
- ããããããŒãããŒããŒã«å
¥ãã
- äœæãããããŒããŒã䜿çšããŠãã€ã³ã¿ãŒãã§ãŒã¹ã®å°ãªããšã1ã€ã®å®è£
ãããŒãããããšããŠããŸãã
ServiceLoaderãã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£
ã確èªããã«ã¯ã META-INF/services
ãã£ã¬ã¯ããªã«ã€ã³ã¿ãŒãã§ã€ã¹ã®ãã«ããŒã ã§ãã¡ã€ã«ãäœæããå¿
èŠããããŸãã
+---es-v1/ | +---src/ | +---main/ | +---resources/ | +---META-INF/ | +---services/ | +---elasticsearch.client.spi.SearchClient +---es-v2/ +---src/ +---main/ +---resources/ +---META-INF/ +---services/ +---elasticsearch.client.spi.SearchClient
ãããŠãåè¡ã«ãã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããã¯ã©ã¹ã®å®å
šãªååãæžããŸãããã®å Žåãã¢ãžã¥ãŒã«ããšã«1ã€ã®SearchClientImpl
ã§ãã
es-v1ã®å Žå ããã¡ã€ã«ã«æ¬¡ã®è¡ããããŸãã
elasticsearch.client.v1.SearchClientImpl
es-v2ã®å Žå ïŒ
elasticsearch.client.v2.SearchClientImpl
ãŸãã maven-dependency-plugin
ã䜿çšããŠã es-v * modules/es-v*/
ãmodules/es-v*/
ã«ã³ããŒãmodules/es-v*/
ã ãããžã§ã¯ãããªãã«ãããŸãã
mvn clean package
ãããŠå®è¡ïŒ
. 29, 2017 10:50:17 org.elasticsearch.plugins.PluginsService <init> INFO: [es1] loaded [], sites [] . 29, 2017 10:50:20 org.elasticsearch.plugins.PluginsService <init> INFO: [es2] modules [], plugins [], sites [] Client for version: 1.7.5 Found doc: {field=test 1} Client for version: 2.4.5 Found doc: {field=test 2}
ãã°ããããæãŸããçµæãåã³åŸãããŸãã
åè¿°ã®ããŒãã³ã¢ã®å Žåã SearchClient
ã€ã³ã¿ãŒãã§ã€ã¹ãå¥ã®spiã¢ãžã¥ãŒã«ã«SearchClient
ã次ã®ããŒããŒãã§ãŒã³ã䜿çšããå¿
èŠããããŸãã
core: bootstrap -> system spi: bootstrap -> spi es-v1: bootstrap -> spi -> es-v1 es-v2: bootstrap -> spi -> es-v2
ã€ãŸã
- spiçšã«å¥ã®ããŒãããŒããŒãäœæããŸãïŒèŠªã§ã¯nullãã¹ããŒããŸã-ããŒãã¹ãã©ããããŒãããŒããŒã䜿çšãããŸãïŒã
- spi ïŒ
SearchClient
ã€ã³ã¿ãŒãã§ãŒã¹ïŒã§ããŒããã - 次ã«ã es-v *ã¢ãžã¥ãŒã«ããšã«ããŒããŒãäœæããŸããããã«ã¯ã spiããŒããŒã芪ãšããŠå«ãŸããŸã
- ...
- å©çïŒ
OSGiã¢ãžã¥ãŒã«
ç§ã¯ããã«æ£çŽã«åçœããŸã-ç§ã¯OSGiãã¬ãŒã ã¯ãŒã¯ã«åºäŒã£ãããšããããŸããïŒããã¯è¯ãããšã§ããïŒïŒã Apache FelixãšEclipse Equinoxã®åå¿è
ãããèŠããšããããã¯ïŒæåã§ïŒãã³ãã«ãããŒããããã³ã³ããã«äŒŒãŠããŸãã åã蟌ã¿ã®å®è£
ããã£ããšããŠããããã¯åçŽãªã¢ããªã±ãŒã·ã§ã³ã«ãšã£ãŠã¯é¢åã§ãã ç§ãééã£ãŠããå Žåã¯ãå察ã®èŠç¹ãã³ã¡ã³ãã§è¡šçŸããŸãïŒå®éã誰ãããããã©ã®ããã«äœ¿çšããŠããããèŠããã§ãïŒ ã
ç§ã¯ãã®åé¡ã«æ·±ãå
¥ããŸããã§ããããªããªã Java 9ã§ã¯ãã¢ãžã¥ãŒã«ã¯ããã«äœ¿çšã§ããããã«ãªããŸãããããã«ã€ããŠèª¬æããŸãã
Javaã®ãã€ãã£ãã¢ãžã¥ãŒã«ïŒ
å
é±ããã©ãããã©ãŒã ã®9çªç®ã®ããŒãžã§ã³ããªãªãŒã¹ãããŸãããäž»ãªé©æ°ã¯ãã©ã³ã¿ã€ã ãšãã©ãããã©ãŒã èªäœã®ãœãŒã¹ã³ãŒãã®ã¢ãžã¥ãŒã«åã§ããã ãŸãã«å¿
èŠãªãã®ã§ãïŒ
ãã³ãïŒã¢ãžã¥ãŒã«ã䜿çšããã«ã¯ã JDK 9ããŸã ããŠã³ããŒãããŠããªãå Žåã¯ããŸãããŠã³ããŒãããŠã€ã³ã¹ããŒã«ããå¿
èŠããããŸã ã
ããã§å¯äžè€éãªã®ã¯ã9ã®äžã§ã¢ãžã¥ãŒã«ãšããŠå®è¡ããããã«äœ¿çšãããã©ã€ãã©ãªã®æ©èœã§ãïŒå®éãIntelliJ IDEAã§module-pathãšãšãã«class-pathãæå®ããæ¹æ³ãèŠã€ãããªãã£ããããmodule-pathã®ã³ã³ããã¹ãã§ãã¹ãŠãå®è¡ããŸãïŒã
ã¢ãžã¥ã©ãŒã·ã¹ãã ã®ä»çµã¿
ã¢ãžã¥ã©ãŒã·ã¹ãã çšã«ã¢ããªã±ãŒã·ã§ã³ã®ã³ãŒããå€æŽããåã«ããŸããããã©ã®ããã«æ©èœããããèŠã€ããŸãïŒç§èªèº«ã¯ãã®åé¡ãç解ãå§ããã°ãããªã®ã§ãééã£ãŠãããããããŸããïŒã
äžèšã®ã¢ãžã¥ãŒã«ã«å ããŠãããããå«ãã¬ã€ã€ãŒããããŸãã ã¢ããªã±ãŒã·ã§ã³ãboot
ãšãã¢ããªã±ãŒã·ã§ã³ãæ§æãã--module-path
ã§æå®ããããã¹ãŠã®ã¢ãžã¥ãŒã«ãããŒããããboot
å±€ãäœæããããããã®äŸåé¢ä¿ïŒãã¹ãŠã®ã¢ãžã¥ãŒã«ã¯èªåçã«java.base
ã¢ãžã¥ãŒã«ã«äŸåããŸãïŒã ä»ã®ã¬ã€ã€ãŒã¯ããã°ã©ã ã§äœæã§ããŸãã
åå±€ã«ã¯ç¬èªã®ã¯ã©ã¹ããŒããŒïŒãŸãã¯éå±€ïŒããããŸãã ããŒãããŒããŒãšåæ§ã«ãã¢ãžã¥ã©ãŒã¬ã€ã€ãŒãéå±€çã«æ§ç¯ã§ããŸãã ãã®ãããªéå±€ã§ã¯ãããå±€ã®ã¢ãžã¥ãŒã«ã¯ã芪局ã«ããä»ã®ã¢ãžã¥ãŒã«ãèŠãããšãã§ããŸãã
ã¢ãžã¥ãŒã«èªäœã¯äºãã«åé¢ãããŠãããããã©ã«ãã§ã¯ãã¢ãžã¥ãŒã«å
ã®ããã±ãŒãžãšã¯ã©ã¹ã¯ä»ã®ã¢ãžã¥ãŒã«ããã¯èŠããŸããã ã¢ãžã¥ãŒã«èšè¿°åïŒ module-info.java
ïŒã䜿çšãããšãåã¢ãžã¥ãŒã«ãéãããšãã§ããããã±ãŒãžãšãäŸåããã¢ãžã¥ãŒã«ãšãã®ããã±ãŒãžãæå®ã§ããŸãã ããã«ãã¢ãžã¥ãŒã«ã¯ãäœæ¥äžã«ç¹å®ã®ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠããããšãéç¥ãããããã®ã€ã³ã¿ãŒãã§ã€ã¹ã®å©çšå¯èœãªå®è£
ãéç¥ããå ŽåããããŸãã ãã®æ
å ±ã¯ãã¢ãžã¥ãŒã«ããã€ã³ã¿ãŒãã§ã€ã¹å®è£
ãããŒãããããã«ServiceLoader APIã«ãã£ãŠäœ¿çšãããŸãã
ã¢ãžã¥ãŒã«ã¯æ瀺çãã€èªåã§ãïŒããã«å€ãã®ã¿ã€ãããããŸããããããã«éå®ããŸãïŒã
- æ瀺çãªã¢ãžã¥ãŒã«ã¯ãjar-archiaïŒã¢ãžã¥ãŒã«ãŸãã¯ã¢ãžã¥ãŒã«åãããjarïŒã®ã«ãŒãã«ãããã¡ã€ã«èšè¿°å
module-info.class
ã«ãã£ãŠæ瀺çã«èšè¿°ãããŸãã - èªåã¢ãžã¥ãŒã«ã¯ãã¢ãžã¥ãŒã«ãã¹ã«é
眮ãããèšè¿°åã®ãªãã©ã€ãã©ãªã§ãã ãã®ã¿ã€ãã®ã¢ãžã¥ãŒã«ãšããŠãå€ãè¯ã
class-path
䜿çšãããŠããæ¢åã®ã¢ãžã¥ãŒã«åãããŠããªãã©ã€ãã©ãªã䜿çšããããšã«ãªã£ãŠãclass-path
ã
ããã§ããã®æ
å ±ããããžã§ã¯ãã«é©çšããã®ã«ååã«ãªããŸãã
- ããŒãã¬ã€ã€ãŒã«ã¯ã ã³ã¢ã¢ãžã¥ãŒã«ã®ã¿ããããŸãã es-v *ã¢ãžã¥ãŒã«ãå«ãŸããå Žåã
elasticsearch.shaded
æšç§»çã¢ãžã¥ãŒã«ã競åãããããã¢ããªã±ãŒã·ã§ã³ã¯èµ·åããŸããã Searcher
ã¯ã©ã¹ã¯ãServiceLoader APIã䜿çšããŠãã¯ã©ã¹ããŒããŒã§es-v *ã¢ãžã¥ãŒã«ãåå¥ã®åã¬ã€ã€ãŒã«æåã§ããŒãããŸãã
ããã¯ç°¡åã§ããïŒ...
ããã±ãŒãžå°ç
ã¢ãžã¥ãŒã«ã¯ïŒå°ãªããšã1ã€ã®ã¬ã€ã€ãŒã§ïŒããã±ãŒãžåãéè€ãããããšã¯ã§ããŸããã
ããšãã°ããããªãã¯ã¯ã©ã¹Functions
ããçš®ã®APIãæäŸããç¹å®ã®ã©ã€ãã©ãªããããŸãã ãã®ã©ã€ãã©ãªã«ã¯ããããã¹ã³ãŒããæã€Helpers
ã¯ã©ã¹ããããŸãã ããã«ãããŸãïŒ
com.foo.bar public class Functions class Helpers
2çªç®ã®ã©ã€ãã©ãªãã·ãŒã³ã«å
¥ããæåã®ã©ã€ãã©ãªã®æ©èœãè£å®ããŸãã
com.foo.baz public class Additional
ãããŠã圌女ã¯éããHelpers
ã¯ã©ã¹ã®æ©èœãå¿
èŠãšããŸãã åãããã±ãŒãžã«ããã€ãã®ã¯ã©ã¹ãé
眮ããããšã§ãç¶æ³ããæãåºããŸãã
com.foo.baz public class Additional com.foo.bar public class AccessorToHelpers
ããã§ãšãããããŸã-ã¢ãžã¥ã©ãŒã·ã¹ãã ã®èŠ³ç¹ããåå²ããã±ãŒãžã®åé¡ãäœæããŸããã ãã®ãããªã©ã€ãã©ãªã§äœãã§ããŸããïŒ ãã®ãããªã©ã€ãã©ãªãã¯ã©ã¹ãã¹ã«æ®ã ãèªåã¢ãžã¥ãŒã«ãããªããžãšããŠäœ¿çšããŠãã¢ãžã¥ãŒã«ãããããã«å°éããããšãææ¡ãããŠããŸãã ããããç°¡åãªæ¹æ³ãæ¢ããŠããããã§ã¯ãªãã®ã§ãå¥ã®ãªãã·ã§ã³ã䜿çšããŸãããã¹ãŠã®äŸåé¢ä¿ãã©ã€ãã©ãªã«å ±åããåäžã®jarã¢ãŒã«ã€ãïŒãã¡ããjarããã³uber jarãšããŠç¥ãããŠããŸãïŒãååŸããã¢ãžã¥ãŒã«ãã¹ã§èªåã¢ãžã¥ãŒã«ãšããŠäœ¿çšã§ããŸããã¯ã©ã¹ãã¹ããã€ãã¹ããŸãã åé¡ã¯ããã®ãããªãªãŒã«ã€ã³ã¯ã³jarãäœæããããšã§ãã
Elasticsearchã®åçµã¿ç«ãŠæé Elasticsearchã¯ãããã±ãŒãžãã©ã€ããŒãã¡ãœãã/ãã£ãŒã«ããžã®ã¢ã¯ã»ã¹ãç©æ¥µçã«äœ¿çšããŠãäžéšã®Luceneæ©èœã«ã¢ã¯ã»ã¹ããŸãã ãããèªåã¢ãžã¥ãŒã«ãšããŠäœ¿çšããã«ã¯ããããuber jarã«ããŠããããžã§ã¯ãã§ããã«äœ¿çšããããã«elasticsaerch-shaded
ãšããååã§ããŒã«ã«ãªããžããªã«ã€ã³ã¹ããŒã«ããŸãã
Elasticsearch 1.7ããã«ããã
æåã®ããŒãžã§ã³ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ããå¯äžã®Mavenã¢ãžã¥ãŒã«ã§ãããããããã§åé¡ã¯çºçããŸããpom.xml
çªç®ã®ã¢ãžã¥ãŒã«ãpom.xml
å Žåã pom.xml
ãšããã€ãã®ã¯ã©ã¹ãä¿®æ£ããå¿
èŠããããŸãã
ãªããžããªããããã£ã¬ã¯ããªã«è€è£œããv1.7.5ã¿ã°ããã§ãã¯ã¢ãŠãããŠv1.7.5
ãéå§ãv1.7.5
ã
- ãã®ãããžã§ã¯ãã¯ãã§ã«
maven-shade-plugin
䜿çšããŠãããããuberjarããã«ãããã«ã¯ãããã€ãã®ããã±ãŒãžãå«ãŸããŠããããšãã³ã¡ã³ãã¢ãŠãããŠããã¹ãŠãå«ãŸããããã«ããå¿
èŠããããŸãã
ã§ããã°å
ã®ãåãã®ãªããã®ïŒ
- ã³ã¡ã³ãã¢ãŠãããã
<includes>
ããŒãã®çŽåŸã«<excludes>
è¿œå ããããšã«ãããGroovyïŒ ãã®ãããªãããŸããã®ããã«è² è·ãäžæããŸãïŒãšãã¬ãŒïŒãããã®èšå®ã¯ãããŸãããJULã¯ããã©ã«ãã§æ£åžžã«åäœããŸãïŒãåé€ããå¿
èŠããããŸãã
<excludes> <exclude>org.codehaus.groovy:groovy-all</exclude> <exclude>org.slf4j:*</exclude> <exclude>log4j:*</exclude> </excludes>
- æªäœ¿çšã¯ã©ã¹ã®åæããªãã«ããŸã-ãã©ã°ã€ã³ã¯ServiceLoader / Reflection APIãèªèããŸããïŒ
- ãããŠãServiceLoader APIã®å®è£
ã¯ã©ã¹ãæã€ãµãŒãã¹ãã¡ã€ã«ã®æ¥çããã©ã°ã€ã³ã®
<configuration>
ããŒãã«è¿œå ããŸãã
<transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers>
pom.xml
å®æããããã java.lang.management.RuntimeMXBean#getBootClassPath
ãã¹ããŒããUnsupportedOperationException
ãæé€ããããã«æ®ã£ãŠãjava.lang.management.RuntimeMXBean#getBootClassPath
ã ãããè¡ãã«ã¯ã JvmInfo
ã¯ã©ã¹ã§æ¬¡ã®è¡ãèŠã€ããŸãã
info.bootClassPath = runtimeMXBean.getBootClassPath();
ããããæ£ãããã®ãã«å®ãïŒ
if (runtimeMXBean.isBootClassPathSupported()) { info.bootClassPath = runtimeMXBean.getBootClassPath(); } else { info.bootClassPath = ""; }
ãã®æ
å ±ã¯çµ±èšã«ã®ã¿äœ¿çšãããŸãã
å®äºãjarããã«ãã§ããããã«ãªããŸããïŒ
$ mvn package
ã³ã³ãã€ã«ãšã¢ã»ã³ããªã®åŸãå¿
èŠãªelasticsearch-1.7.5.jar
ãtarget
ãã£ã¬ã¯ããªã«elasticsearch-1.7.5.jar
ããŸãã 次ã«ãããšãã°elasticsearch-shaded
ãšããååã§ãããŒã«ã«ãªããžããªã«ã€ã³ã¹ããŒã«ããå¿
èŠããããŸãã
$ mvn install:install-file \ > -Dfile=elasticsearch-1.7.5.jar \ > -DgroupId=org.elasticsearch \ > -DartifactId=elasticsearch-shaded \ > -Dversion=1.7.5 \ > -Dpackaging=jar \ > -DgeneratePom=true
ããã§ããã®ã¢ãŒãã£ãã¡ã¯ãães-v1 Mavenã¢ãžã¥ãŒã«ã®èªåã¢ãžã¥ãŒã«ãšããŠäœ¿çšã§ããŸãã
<dependencies> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch-shaded</artifactId> <version>1.7.5</version> </dependency> ... </dependencies>
Elasticsearch 2.4ããã«ããã
ããŒã«ã«ã®å€æŽãããŒã«ããã¯ãã v2.4.5
ã¿ã°ã«ã¿ã°ãä»ããŸãã 2çªç®ã®ããŒãžã§ã³ããããããžã§ã¯ãã¯ã¢ãžã¥ãŒã«ã«åå²ãããŸãã elasticsearch-2.4.5.jar
çºè¡ããããã«å¿
èŠãªã¢ãžã¥ãŒã«ãã³ã¢ã¢ãžã¥ãŒã«ã§ãã
- æåã«ã¹ãããã·ã§ãããåé€ããŸãããªãªãŒã¹ãå¿
èŠã§ãã
$ mvn versions:set -DnewVersion=2.4.5
- ããã§ãã·ã§ãŒããã©ã°ã€ã³ãã©ãã§èšå®ãããŠããããèŠãŠã¿ãŸããã...ãããŠããã®ãããªããã¯ã«ééããŸãïŒ
ã·ã§ãŒãã£ã³ã°ãšããã±ãŒãžã®åé
眮ãåé€ãããŸãã
Elasticsearchã¯ãäŸåé¢ä¿ãã·ã§ãŒãã£ã³ã°ããããã±ãŒãžãåé
眮ããããã«äœ¿çšãããŠããŸããã ã·ã§ãŒãã£ã³ã°ãåé
眮ã¯äœ¿çšããªããªããŸããã
ã€ã³ããŒããå
ã®ããã±ãŒãžåã«å€æŽããå¿
èŠãããå ŽåããããŸãã
com.google.common
ã¯org.elasticsearch.common
com.carrotsearch.hppc
ã¯org.elasticsearch.common.hppc
jsr166e
ã¯org.elasticsearch.common.util.concurrent.jsr166e
...
ã³ã¢ã¢ãžã¥ãŒã«ã«å床ã·ã§ãŒããã©ã°ã€ã³ãè¿œå ãããµãŒãã¹ãã¡ã€ã«ã®ãã©ã³ã¹ãã©ãŒããŒãšãã¬ãŒã®é€å€ãèšå®ã«è¿œå ããå¿
èŠããããŸãã
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> <artifactSet> <excludes> <exclude>org.slf4j:*</exclude> <exclude>log4j:*</exclude> </excludes> </artifactSet> </configuration> </plugin>
- ã³ã¢ã¢ãžã¥ãŒã«ã®
com.twitter:jsr166e
ïŒ9-keã«ã¯ååšããªãsun.misc.Unsafe
䜿çšïŒãåé€ããŸãã
ã€ã³ããŒãcom.twitter.jsr166e
ãjava.util.concurrent.atomic
å€æŽããŸãã
animal-sniffer-maven-plugin
åã®ã¹ãããã®å€æŽanimal-sniffer-maven-plugin
æ€åºãïŒ7-keã«ã¯jsr166eã¯ãããŸããïŒãåé€ããŸãïŒ
å®äºã es-v1ãšåãã¢ã»ã³ããªããã³ã€ã³ã¹ããŒã«æé ãå®è¡ããŠããŸãããããããªéãããããŸãã
- ããŒãžã§ã³ã2.4.5ã«å€æŽãã
- ã³ã¢ã¢ãžã¥ãŒã«ããã«ãããã ãã§ãã
$ mvn clean package -pl org.elasticsearch:parent,org.elasticsearch:elasticsearch -DskipTests=true
ç§ãã¡ã®ãããžã§ã¯ãã®ã¢ãžã¥ãŒã«
䜿çšããã©ã€ãã©ãªãã¢ãžã¥ã©ãŒJavaã·ã¹ãã ã§æ©èœããããšãããã£ãåŸãMavenã¢ãžã¥ãŒã«ããæ瀺çãªJavaã¢ãžã¥ãŒã«ãäœæããŸãã ãããè¡ãã«ã¯ããœãŒã¹ïŒ src/main/java
ïŒã䜿çšããŠåãã£ã¬ã¯ããªã«module-info.java
ãã¡ã€ã«ãäœæãããããã®ã¢ãžã¥ãŒã«éã®é¢ä¿ãèšè¿°ããå¿
èŠããããŸãã
ã³ã¢ã¢ãžã¥ãŒã«ã¯ä»ã®ã¢ãžã¥ãŒã«ã«äŸåãããä»ã®ã¢ãžã¥ãŒã«ãå®è£
ããå¿
èŠãããã€ã³ã¿ãŒãã§ã€ã¹ã®ã¿ãå«ãããã説æã¯æ¬¡ã®ããã«ãªããŸãã
es-v1ããã³es-v2ã¢ãžã¥ãŒã«ã«ã€ããŠãåæ§ã®èª¬æããããŸãã
- 圌ãã¯
elasticsearch.client.core
ã¢ãžã¥ãŒã«ã䜿çšããŸãããªããªã ã€ã³ã¿ãŒãã§ãŒã¹ããããŸã - ãããããå¿
èŠãªããŒãžã§ã³ã®Elasticsearchèªåã¢ãžã¥ãŒã«ã䜿çšãã
- åã¢ãžã¥ãŒã«ã¯ã
SearchClient
ã€ã³ã¿ãŒãã§ãŒã¹ã®å®è£
ãæäŸããããšãSearchClient
ãŸãã
es-v1ã®åèšïŒ
es-v2ã®å Žåãã»ãšãã©ãã¹ãŠãåãã§ãããããŒãžã§ã³v2
ã®ã¿ãååã«è¡šç€ºãããŸãã
次ã«ããã®ãããªã¢ãžã¥ãŒã«ãããŒãããæ¹æ³ã¯ïŒ ãã®è³ªåã«å¯Ÿããçãã¯ãFSããã¢ãžã¥ãŒã«ãããŒãããå°ããªäŸãå«ãModuleLayerã¯ã©ã¹ã®èª¬æã«ãããŸãã ãã¹ãŠã®es-v *ã¢ãžã¥ãŒã«ãåããã£ã¬ã¯ããªmodules/es-v*/
ã«ãããšä»®å®ãããšã次ã®ããã«æžãããšãã§ããŸãã
private static SearchClient getClient(String desiredVersion) throws Exception { Path modPath = Paths.get("modules", "es-v" + desiredVersion); ModuleFinder moduleFinder = ModuleFinder.of(modPath); ModuleLayer parent = ModuleLayer.boot(); Configuration config = parent.configuration().resolve(moduleFinder, ModuleFinder.of(), Set.of("elasticsearch.client.v" + desiredVersion)); ModuleLayer moduleLayer = parent.defineModulesWithOneLoader(config, Thread.currentThread().getContextClassLoader()); ServiceLoader<SearchClient> serviceLoader = ServiceLoader.load(moduleLayer, SearchClient.class); Optional<SearchClient> searchClient = serviceLoader.findFirst(); if (searchClient.isPresent()) { return searchClient.get(); } throw new Exception("Module 'elasticsearch.client.v" + desiredVersion + "' not found on " + modPath); }
ModuleLayer#defineModulesWithManyLoaders , es-v* .
, . maven-compiler-plugin
, â 3.7.0:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin>
Java 9 :
<properties> <maven.compiler.source>1.9</maven.compiler.source> <maven.compiler.target>1.9</maven.compiler.target> </properties>
maven-dependency-plugin
, :
$ mvn clean package
, :
. 29, 2017 10:59:01 org.elasticsearch.plugins.PluginsService <init> INFO: [es1] loaded [], sites [] . 29, 2017 10:59:04 org.elasticsearch.plugins.PluginsService <init> INFO: [es2] modules [], plugins [], sites [] Client for version: 1.7.5 Found doc: {field=test 1} Client for version: 2.4.5 Found doc: {field=test 2}
, â , , Java 8 .
çµãã
, /. :
- ClassLoader â ,
( ), - ServiceLoader API â META-INF/services,
- , ( ) â
- Java 9 â .
PS Java 9!