Upgrade to Pro — share decks privately, control downloads, hide ads and more …

War Story: Как мы внедряли поддержку Java 11 в Jenkins (RUS)

War Story: Как мы внедряли поддержку Java 11 в Jenkins (RUS)

Сказ о том, как мы внедряли поддержку Java 11 в Jenkins — одном из наиболее популярных серверов автоматизации для CI/CD. Цель доклада — рассказать о том, с какими проблемами мы столкнулись в реальном крупном Maven-проекте, и о том, как мы их решали. Доклад не имеет отношения к Jenkins как таковому, целевая аудитория — разработчики, которые планируют переезд на Java 11.

Как нам удалось поддержать Java 11 и сохранить совместимость с Java 8? Как мы обеспечили сборку и тестирование проектов в Java 9..11? Насколько на нас повлияли новая система модулей, multi-release JARs и несовместимые изменения в Java (reflection, classloading, удаление компонентов Java EE/Jakarta)? И как автоматизировать тестирование, чтобы не переделывать всё с каждым новым релизом Java? И что мы, в конце концов, получили от миграции на Java 11?

Справка: Jenkins имеет огромную кодовую базу: Java, Groovy, нативные библиотеки и даже немного Kotlin. Проект включает сотни зависимостей, 1500+ плагинов, а также десятки стандартных и самописных dev-тулов (Maven, Gradle). Впридачу — 10 лет обратной совместимости и огромное количество легаси-кода. Если вы заметили сходство со своими Java-проектами и думаете о миграции на Java 11, то приходите на доклад :)

Oleg Nenashev

October 26, 2019
Tweet

More Decks by Oleg Nenashev

Other Decks in Technology

Transcript

  1. © 2019 CloudBees, Inc. All Rights Reserved.
    © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins.war story
    Как мы внедряли поддержку Java 11
    Олег Ненашев, CloudBees
    @oleg_nenashev

    View Slide

  2. © 2019 CloudBees, Inc. All Rights Reserved.
    О чём доклад?
    V - Миграция крупных
    проектов на Java 11
    V - Наш опыт, проблемы и
    решения
    V - Java, Maven,
    стандартные тулы
    X - Jenkins
    X - Jenkins X
    X - Дебри Java 11
    2

    View Slide

  3. © 2019 CloudBees, Inc. All Rights Reserved.
    > whoami
    @oleg_nenashev
    oleg-nenashev
    • Principal SW Engineer, CloudBees
    • Jenkins Core maintainer
    • Platform SIG leader
    3

    View Slide

  4. © 2019 CloudBees, Inc. All Rights Reserved.
    > whoami -cloudbees
    4

    CloudBees Jenkins Distribution

    CloudBees Jenkins Support

    Сообщество: Java 11, Jenkinsfile Runner, JCasC
    https://www.cloudbees.com

    View Slide

  5. © 2019 CloudBees, Inc. All Rights Reserved.
    Who is Mr. Jenkins?
    1. Сервер автоматизации
    2. CI/CD/DevOps/…
    3. 200k+ инсталляций
    4. Open-source
    5. Большое сообщество
    6. >1700 плагинов
    https://jenkins.io
    5

    View Slide

  6. © 2019 CloudBees, Inc. All Rights Reserved.
    Under the hood
    JENKINS
    Image: https://www.youtube.com/watch?v=Qae_3RDa6sM 6

    View Slide

  7. © 2019 CloudBees, Inc. All Rights Reserved.
    7

    View Slide

  8. © 2019 CloudBees, Inc. All Rights Reserved.
    8
    Более 50 тикетов на
    совместимость с
    Java 9/10

    View Slide

  9. © 2019 CloudBees, Inc. All Rights Reserved.
    Java 8 навсегда?
    9

    View Slide

  10. © 2019 CloudBees, Inc. All Rights Reserved.
    Java 8 навсегда?
    10

    View Slide

  11. © 2019 CloudBees, Inc. All Rights Reserved.
    8
    11

    View Slide

  12. © 2019 CloudBees, Inc. All Rights Reserved.
    12

    View Slide

  13. © 2019 CloudBees, Inc. All Rights Reserved.
    13

    View Slide

  14. © 2019 CloudBees, Inc. All Rights Reserved.
    Июнь 2018 - Online Hackathon
    ● 1й день - Pipeline
    14

    View Slide

  15. © 2019 CloudBees, Inc. All Rights Reserved.
    Июнь 2018 - Online Hackathon
    ● 2й день - BlueOcean
    15

    View Slide

  16. © 2019 CloudBees, Inc. All Rights Reserved.
    Июнь 2018 - Online Hackathon
    ● 5й день - “самое скучное
    демо на свете”
    16

    View Slide

  17. © 2019 CloudBees, Inc. All Rights Reserved.
    Сентябрь 2018
    ● 1 день - поддержка Java 11
    17

    View Slide

  18. © 2019 CloudBees, Inc. All Rights Reserved.
    Java 10 PoC -
    июнь 2018
    Java 11 PoC -
    сентябрь 2018
    Java 11 RC -
    декабрь 2018
    Java 11 GA -
    март 2019
    18
    ? ? ?

    View Slide

  19. © 2019 CloudBees, Inc. All Rights Reserved.
    Запустить проект на Java 11 - легко,
    а переехать на Java 11 - сложно
    19

    View Slide

  20. © 2019 CloudBees, Inc. All Rights Reserved.
    Экосистема Jenkins
    Ядро и модули
    Плагины
    Дистрибутивы
    Подпроекты
    Библиотеки
    Средства разработки
    20

    View Slide

  21. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    Наш
    Pipeline
    21

    View Slide

  22. © 2019 CloudBees, Inc. All Rights Reserved.
    Наши тулы

    Maven и немного Gradle

    Parent POM и BOM

    Maven SureFire + JUnit 4

    SpotBugs, Animal Sniffer, Maven Enforcer

    JaCoCo и Cobertura

    Свои Maven-плагины
    22

    View Slide

  23. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    > mvn clean package -Djava.level = 11
    23
    Попытка 1: Maven Compiler
    Plugin: Unsupported target: 1.11
    Попытка 2: Maven Compiler
    Plugin: Unsupported target: 11

    View Slide

  24. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    Maven-плагины
    24

    View Slide

  25. © 2019 CloudBees, Inc. All Rights Reserved.
    Maven-плагины
    25
    > mvn versions:display-plugin-updates
    ...

    View Slide

  26. © 2019 CloudBees, Inc. All Rights Reserved.
    Maven-плагины
    Maven Compiler Plugin
    Maven Enforcer & Rule Plugin
    Maven Site
    GMaven/GMavenPlus
    Javadoc
    ...
    > mvn versions:display-plugin-updates
    26

    View Slide

  27. © 2019 CloudBees, Inc. All Rights Reserved.
    27
    java.lang.IllegalArgumentException
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:185)
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:168)
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.reader(…)
    ….
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.getCommonSuperClass(...)
    at org.jenkinsci.bytecode.NonClassLoadingClassWriter.getCommonSuperClass(NonClassLoadingClassWriter.java:72)
    at org.kohsuke.asm6.ClassWriter.getMergedType(ClassWriter.java:1736)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1530)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1478)
    at org.kohsuke.asm6.MethodWriter.visitMaxs(MethodWriter.java:1520)
    at org.kohsuke.asm6.tree.MethodNode.accept(MethodNode.java:835)
    at org.kohsuke.asm6.commons.JSRInlinerAdapter.visitEnd(JSRInlinerAdapter.java:187)
    at org.jenkinsci.bytecode.Transformer$1$1.visitEnd(Transformer.java:109)
    at org.kohsuke.asm6.MethodVisitor.visitEnd(MethodVisitor.java:878)
    at org.kohsuke.asm6.ClassReader.readMethod(ClassReader.java:1169)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:727)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:525)
    at org.jenkinsci.bytecode.Transformer.transform(Transformer.java:115)
    at hudson.ClassicPluginStrategy$AntClassLoader2.defineClassFromData(ClassicPluginStrategy.java:857)
    at jenkins.util.AntClassLoader.getClassFromStream(AntClassLoader.java:1311)
    at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1364)
    at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327)
    at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.(CpsScript.java:69)
    at WorkflowScript.(WorkflowScript

    View Slide

  28. © 2019 CloudBees, Inc. All Rights Reserved.
    28
    java.lang.IllegalArgumentException
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:185)
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:168)
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.reader(…)
    ….
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.getCommonSuperClass(...)
    at org.jenkinsci.bytecode.NonClassLoadingClassWriter.getCommonSuperClass(NonClassLoadingClassWriter.java:72)
    at org.kohsuke.asm6.ClassWriter.getMergedType(ClassWriter.java:1736)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1530)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1478)
    at org.kohsuke.asm6.MethodWriter.visitMaxs(MethodWriter.java:1520)
    at org.kohsuke.asm6.tree.MethodNode.accept(MethodNode.java:835)
    at org.kohsuke.asm6.commons.JSRInlinerAdapter.visitEnd(JSRInlinerAdapter.java:187)
    at org.jenkinsci.bytecode.Transformer$1$1.visitEnd(Transformer.java:109)
    at org.kohsuke.asm6.MethodVisitor.visitEnd(MethodVisitor.java:878)
    at org.kohsuke.asm6.ClassReader.readMethod(ClassReader.java:1169)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:727)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:525)
    at org.jenkinsci.bytecode.Transformer.transform(Transformer.java:115)
    at hudson.ClassicPluginStrategy$AntClassLoader2.defineClassFromData(ClassicPluginStrategy.java:857)
    at jenkins.util.AntClassLoader.getClassFromStream(AntClassLoader.java:1311)
    at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1364)
    at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327)
    at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.(CpsScript.java:69)
    at WorkflowScript.(WorkflowScript
    at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.(CpsScript.java:69)
    at WorkflowScript.(WorkflowScript

    View Slide

  29. © 2019 CloudBees, Inc. All Rights Reserved.
    29
    java.lang.IllegalArgumentException
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:185)
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:168)
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.reader(…)
    ….
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.getCommonSuperClass(...)
    at org.jenkinsci.bytecode.NonClassLoadingClassWriter.getCommonSuperClass(NonClassLoadingClassWriter.java:72)
    at org.kohsuke.asm6.ClassWriter.getMergedType(ClassWriter.java:1736)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1530)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1478)
    at org.kohsuke.asm6.MethodWriter.visitMaxs(MethodWriter.java:1520)
    at org.kohsuke.asm6.tree.MethodNode.accept(MethodNode.java:835)
    at org.kohsuke.asm6.commons.JSRInlinerAdapter.visitEnd(JSRInlinerAdapter.java:187)
    at org.jenkinsci.bytecode.Transformer$1$1.visitEnd(Transformer.java:109)
    at org.kohsuke.asm6.MethodVisitor.visitEnd(MethodVisitor.java:878)
    at org.kohsuke.asm6.ClassReader.readMethod(ClassReader.java:1169)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:727)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:525)
    at org.jenkinsci.bytecode.Transformer.transform(Transformer.java:115)
    at hudson.ClassicPluginStrategy$AntClassLoader2.defineClassFromData(ClassicPluginStrategy.java:857)
    at jenkins.util.AntClassLoader.getClassFromStream(AntClassLoader.java:1311)
    at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1364)
    at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327)
    at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.(CpsScript.java:69)
    at WorkflowScript.(WorkflowScript
    java.lang.IllegalArgumentException
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:185)
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:168)
    at org.jenkinsci.bytecode.helper.???Reader.reader(…)

    View Slide

  30. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    Maven-плагины
    Зависимости
    30

    View Slide

  31. © 2019 CloudBees, Inc. All Rights Reserved.
    Lib 1 Lib 2 Lib 3
    Plugin 1 Plugin 2 Plugin 3
    Lib 4
    Lib 5
    Plugin 4
    иногда
    31

    View Slide

  32. © 2019 CloudBees, Inc. All Rights Reserved.
    32
    IT IS OVER
    9000 DEPENDENCIES

    View Slide

  33. © 2019 CloudBees, Inc. All Rights Reserved.
    Dependency
    Hell
    33

    View Slide

  34. © 2019 CloudBees, Inc. All Rights Reserved.
    34
    > mvn versions:display-updates
    ...
    ? ? ?

    View Slide

  35. © 2019 CloudBees, Inc. All Rights Reserved.
    Нет фиксов для
    Java 9+
    Несовместимые
    изменения
    Библиотеки
    требуют Java 9+
    Мёртвые проекты
    35

    View Slide

  36. © 2019 CloudBees, Inc. All Rights Reserved.
    ASM
    36
    https://asm.ow2.io/

    View Slide

  37. © 2019 CloudBees, Inc. All Rights Reserved.
    java.lang.IllegalArgumentException
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:185)
    at org.kohsuke.asm6.ClassReader.(ClassReader.java:168)
    at
    org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.reader(ClassLoadingReferenceTypeHierachyReader.java:64)
    ….
    at org.jenkinsci.bytecode.helper.ClassLoadingReferenceTypeHierachyReader.getCommonSuperClass(...)
    at org.jenkinsci.bytecode.NonClassLoadingClassWriter.getCommonSuperClass(NonClassLoadingClassWriter.java:72)
    at org.kohsuke.asm6.ClassWriter.getMergedType(ClassWriter.java:1736)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1530)
    at org.kohsuke.asm6.Frame.merge(Frame.java:1478)
    at org.kohsuke.asm6.MethodWriter.visitMaxs(MethodWriter.java:1520)
    at org.kohsuke.asm6.tree.MethodNode.accept(MethodNode.java:835)
    at org.kohsuke.asm6.commons.JSRInlinerAdapter.visitEnd(JSRInlinerAdapter.java:187)
    at org.jenkinsci.bytecode.Transformer$1$1.visitEnd(Transformer.java:109)
    at org.kohsuke.asm6.MethodVisitor.visitEnd(MethodVisitor.java:878)
    at org.kohsuke.asm6.ClassReader.readMethod(ClassReader.java:1169)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:727)
    at org.kohsuke.asm6.ClassReader.accept(ClassReader.java:525)
    at org.jenkinsci.bytecode.Transformer.transform(Transformer.java:115)
    at hudson.ClassicPluginStrategy$AntClassLoader2.defineClassFromData(ClassicPluginStrategy.java:857)
    at jenkins.util.AntClassLoader.getClassFromStream(AntClassLoader.java:1311)
    at jenkins.util.AntClassLoader.findClassInComponents(AntClassLoader.java:1364)
    at jenkins.util.AntClassLoader.findClass(AntClassLoader.java:1327)
    at jenkins.util.AntClassLoader.loadClass(AntClassLoader.java:1080)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.(CpsScript.java:69)
    at WorkflowScript.(WorkflowScript
    37
    at
    org.jenkinsci.bytecode.Transformer.transform
    (Transformer.java:115)

    View Slide

  38. © 2019 CloudBees, Inc. All Rights Reserved.
    Наш список
    ASM
    Byte Buddy
    Reflections
    Jetty
    Groovy
    JNR, JNA
    Annotation Indexer
    SezPoz
    ...
    38

    View Slide

  39. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Maven Enforcer Plugin
    https://maven.apache.org/enforcer/maven-enforcer-plugin/
    ● Extra Enforcer Rules Plugin
    https://www.mojohaus.org/extra-enforcer-rules/
    Что поможет?
    39

    View Slide

  40. © 2019 CloudBees, Inc. All Rights Reserved.

    maven-enforcer-plugin






    1.8

    test






    extra-enforcer-rules

    40

    View Slide

  41. © 2019 CloudBees, Inc. All Rights Reserved.
    41

    maven-enforcer-plugin






    1.8

    test






    extra-enforcer-rules


    1.8

    test


    View Slide

  42. © 2019 CloudBees, Inc. All Rights Reserved.
    Транзитивные
    зависимости?
    ПОТОМУ ЧТО
    MAVEN
    42

    View Slide

  43. © 2019 CloudBees, Inc. All Rights Reserved.
    Транзитивные зависимости
    ● И снова Maven Enforcer Plugin
    ● requireUpperBoundDeps


    commons-logging:commons-logging
    com.google.code.findbugs:jsr305
    net.java.dev.jna:jna


    43

    View Slide

  44. © 2019 CloudBees, Inc. All Rights Reserved.
    А Вы обновляете зависимости?
    44

    View Slide

  45. © 2019 CloudBees, Inc. All Rights Reserved.
    Технический
    долг
    45

    View Slide

  46. © 2019 CloudBees, Inc. All Rights Reserved.
    Dependabot
    dependabot.com, куплен GitHub
    46

    View Slide

  47. © 2019 CloudBees, Inc. All Rights Reserved.
    Dependabot

    CLI и GitHub App

    Регулярное
    сканирование

    Поддержка Maven,
    Gradle и др.
    47

    View Slide

  48. © 2019 CloudBees, Inc. All Rights Reserved.
    Dependabot
    48
    @oleg_nenashev
    https://speakerdeck.com/onenashev/

    View Slide

  49. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    Maven-плагины
    Зависимости
    Наш код
    49

    View Slide

  50. © 2019 CloudBees, Inc. All Rights Reserved.
    50

    View Slide

  51. © 2019 CloudBees, Inc. All Rights Reserved.
    JEP 261: Module System
    51

    View Slide

  52. © 2019 CloudBees, Inc. All Rights Reserved.
    Никто не заставляет
    использовать модули!
    52

    View Slide

  53. 53
    ONE DOES NOT SIMPLY
    IGNORE MODULES IN JAVA11

    View Slide

  54. © 2019 CloudBees, Inc. All Rights Reserved.
    java.lang.NoClassDefFoundError: java.sql.Date at
    o.a.c.beanutils.ConvertUtilsBean.class$(ConvertUtilsBean.java:157) at
    o.a.c.beanutils.ConvertUtilsBean.registerOther(ConvertUtilsBean.java:708) at
    o.a.c.beanutils.ConvertUtilsBean.deregister(ConvertUtilsBean.java:580) at
    o.a.c.beanutils.ConvertUtilsBean.(ConvertUtilsBean.java:164) at
    org.kohsuke.stapler.Stapler.(Stapler.java:1065) at
    hudson.model.Node$Mode.(Node.java:597) at
    JENKINS-54426
    54

    View Slide

  55. © 2019 CloudBees, Inc. All Rights Reserved.
    http://java9.wtf/class-loading/
    55

    View Slide

  56. © 2019 CloudBees, Inc. All Rights Reserved.
    JEP-261 - Restricted Bootstrap Class Loader
    java.sql.*
    javax.activation.*
    javax.annotation.*
    javax.jws.*
    javax.lang.model.*
    javax.rmi.*
    javax.script.*
    javax.smartcardio.*
    javax.sql.*
    javax.tools.*
    javax.transaction.xa.*
    javax.xml.bind.*
    javax.xml.crypto.*
    javax.xml.soap.*
    javax.xml.ws.*
    56

    View Slide

  57. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Проблема: new URLClassloader(null, ...)
    ● Классы из модулей больше недоступны
    ● getPlatformClassLoader() для Java 9+
    ● А для Java 8 метода нет….
    JEP-261 - Restricted Bootstrap Class Loader
    57

    View Slide

  58. © 2019 CloudBees, Inc. All Rights Reserved.
    Platform Classloader. Решение
    private ClassLoader getPlatformClassloader() throws NoSuchMethodException,
    InvocationTargetException, IllegalAccessException {
    if (isPostJava8()) {
    return (ClassLoader) ClassLoader.class.getMethod
    ("getPlatformClassLoader").invoke(null);
    }
    return null; // Java 8
    }
    private static boolean isPostJava8() {
    String javaVersion = System.getProperty("java.version");
    return !javaVersion.startsWith("1.");
    }
    58

    View Slide

  59. © 2019 CloudBees, Inc. All Rights Reserved.
    Кстати о Reflection...
    WARNING: Illegal reflective access by hudson.remoting.RemoteClassLoader
    (file:/var/jenkins_home/war/WEB-INF/lib/remoting-3.7.jar) to method
    java.lang.ClassLoader.getClassLoadingLock(java.lang.String)
    at h.r.RemoteClassLoader.(RemoteClassLoader.java:330)
    at h.r.MultiClassLoaderSerializer$Output.annotateClass(MultiClassLoaderSerializer.java:69)
    at java.base/java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1291)
    at java.base/java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1232)
    59
    JENKINS-46724

    View Slide

  60. © 2019 CloudBees, Inc. All Rights Reserved.
    Кстати о Reflection...
    WARNING: Illegal reflective access by hudson.remoting.RemoteClassLoader
    (file:/var/jenkins_home/war/WEB-INF/lib/remoting-3.7.jar) to method
    java.lang.ClassLoader.getClassLoadingLock(java.lang.String)
    at h.r.RemoteClassLoader.(RemoteClassLoader.java:330)
    at h.r.MultiClassLoaderSerializer$Output.annotateClass(MultiClassLoaderSerializer.java:69)
    at java.base/java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1291)
    at java.base/java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1232)
    JENKINS-46724
    60
    TL;DR: setAccessible(true) - это плохо
    Crash в Java 9 EA по-умолчанию
    Предупреждение в логах для Java 9+

    View Slide

  61. © 2019 CloudBees, Inc. All Rights Reserved.
    Illegal Reflective Access
    ● Internal Libraries
    ● Upstream Dependencies
    ● Object serialization frameworks
    Escape hatch:
    “--illegal-access=permit”
    61

    View Slide

  62. © 2019 CloudBees, Inc. All Rights Reserved.
    Удалённые компоненты
    sun.misc.Unsafe
    Java Web Start
    JAXB
    CORBA
    API: методы и классы
    ...
    62

    View Slide

  63. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Удалена из JDK
    ● Доступна через Jakarta, но почти не поддерживается
    ● В итоге – свой плагин
    Наша боль – java.xml.bind (JAXB)
    63
    java
    -p jaxb-api.jar:javax.activation.jar
    --add-modules java.xml.bind,java.activation ...
    -cp jaxb-core.jar:jaxb-impl.jar
    -jar jenkins.war …

    View Slide

  64. © 2019 CloudBees, Inc. All Rights Reserved.
    Удалённые API
    64

    View Slide

  65. © 2019 CloudBees, Inc. All Rights Reserved.
    java.lang.UNIXProcess#destroyProcess()
    65

    View Slide

  66. © 2019 CloudBees, Inc. All Rights Reserved.
    Подходы к совместимому коду
    66
    Reflection
    Class#getDeclaredMethod()
    Class#getDeclaredField()
    setAccessible()

    View Slide

  67. © 2019 CloudBees, Inc. All Rights Reserved.
    Подходы к совместимому коду
    67
    Reflection
    Multi-Release JAR
    (JEP-238)
    JAR content root
    A.class
    B.class
    C.class
    META-INF
    MANIFEST.MF
    versions
    9
    A.class
    B.class
    10
    A.class
    Class#getDeclaredMethod()
    Class#getDeclaredField()
    setAccessible()

    View Slide

  68. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    Maven-плагины
    Зависимости
    Наш код
    68

    View Slide

  69. © 2019 CloudBees, Inc. All Rights Reserved.
    Собирать на Java 8,
    тестировать с Java 11?
    69

    View Slide

  70. © 2019 CloudBees, Inc. All Rights Reserved.
    Maven Surefire - Тестирование с Java 11


    maven-surefire-plugin

    /path/to/jdk11/bin/java



    70

    View Slide

  71. © 2019 CloudBees, Inc. All Rights Reserved.
    Maven Surefire - Подключение модулей


    /path/to/jdk11/bin/java
    -p jaxb-api.jar:javax.activation.jar
    --add-modules java.xml.bind,java.activation ...
    -cp jaxb-core.jar:jaxb-impl.jar ...


    71

    View Slide

  72. © 2019 CloudBees, Inc. All Rights Reserved.
    Что не так?
    Тестовые зависимости
    Несовместимые Maven-
    плагины
    Несовместимые тесты
    72

    View Slide

  73. © 2019 CloudBees, Inc. All Rights Reserved.
    Mockito
    ASM, ASM, ASM
    Минимальные версии
    mockito-core 2.23.4+
    Mockito почти совместим
    JENKINS-55098
    73

    View Slide

  74. © 2019 CloudBees, Inc. All Rights Reserved.
    PowerMock
    Минимальные версии
    powermock-module-junit4:2.0.0-RC4
    powermock-api-mockito2:2.0.0-RC4
    objenesis:3.0.1
    PowerMock несовместим
    JENKINS-55098
    74

    View Slide

  75. © 2019 CloudBees, Inc. All Rights Reserved.
    PowerMock
    75

    View Slide

  76. © 2019 CloudBees, Inc. All Rights Reserved.
    Тесты только на Java 8?
    76

    View Slide

  77. © 2019 CloudBees, Inc. All Rights Reserved.
    CORBA*
    77
    * мы её не используем

    View Slide

  78. © 2019 CloudBees, Inc. All Rights Reserved.
    CORBA – Риск RCE при десериализации*
    Мастер Агент
    RPC
    Системные вызовы
    RemoteInputStream/
    RemoteOutputStream
    Classloading
    Сериализация обьектов
    с readResolve()
    * Анонс Foxglove Security, 2015

    View Slide

  79. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Мы не используем CORBA
    ● Но у нас есть тесты на deserialization
    ● Multi-Release Test JAR не работают ☹
    CORBA. Удалена в JDK11 (JEP-320)
    79

    View Slide

  80. © 2019 CloudBees, Inc. All Rights Reserved.
    Тесты только на Java 8?
    80

    View Slide

  81. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    81

    View Slide

  82. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Animal Sniffer
    ● FindBugs => SpotBugs
    ● JaCoCo, Cobertura
    ● Access Modifier (@Restricted)
    ● ...
    Что нам пришлось обновлять?
    82

    View Slide

  83. © 2019 CloudBees, Inc. All Rights Reserved.
    SpotBugs 3.1.8+ (№711)
    83
    FindBugs

    View Slide

  84. © 2019 CloudBees, Inc. All Rights Reserved.
    84
    client.setServerKeyVerifier(verifier);
    client.start();
    try (ClientSession session = cf.getSession()) {
    /// ....
    } finally {
    client.stop();
    }

    View Slide

  85. © 2019 CloudBees, Inc. All Rights Reserved.
    85
    client.setServerKeyVerifier(verifier);
    client.start();
    try (ClientSession session = cf.getSession()) {
    /// ....
    } finally { //
    RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE
    client.stop();
    }

    View Slide

  86. © 2019 CloudBees, Inc. All Rights Reserved.
    SpotBugs 3.1.8+ - не панацея
    86

    View Slide

  87. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    87

    View Slide

  88. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins-on-Jenkins
    88
    1. Зеркала с JDK (ZIP Installer)
    2. Тестовые тулы
    3. Docker-образы агентов
    4. Docker-образы для всех тулов
    5. Библиотеки Pipeline
    6. Сами Pipeline
    https://ci.jenkins.io/

    View Slide

  89. © 2019 CloudBees, Inc. All Rights Reserved.
    Мы слишком
    привыкли к Java 8
    89

    View Slide

  90. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Java 8 и 11
    ● Linux и Windows
    ● Разные версии ядра Jenkins
    ● Версии/дистрибутивы Java
    Конфигурации
    90

    View Slide

  91. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins-on-Jenkins. Сборка ядра
    https://ci.jenkins.io/blue/organizatio
    ns/jenkins/Core%2Fjenkins/detail/j
    ava11-support/18/pipeline
    91

    View Slide

  92. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Jenkins Acceptance Test Harness
    ● Не трогали Selenium ~5 лет…
    ● Минорные изменения, легкий апдейт
    ● Перешли на современные драйверы
    Selenium
    92

    View Slide

  93. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins-on-Jenkins. Сборка плагинов
    93
    // Jenkinsfile
    buildPlugin()
    https://github.com/jenkins-infra/pipeline-library

    View Slide

  94. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins-on-Jenkins. Сборка плагинов
    // Jenkinsfile
    buildPlugin(configurations:
    buildPlugin.recommendedConfigurations())
    94

    View Slide

  95. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins-on-Jenkins. Сборка плагинов
    95

    View Slide

  96. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    96
    Инсталляторы
    Docker

    View Slide

  97. © 2019 CloudBees, Inc. All Rights Reserved.
    OracleJDK / OpenJDK
    Лицензионные соглашения...
    Новая политика в Oracle JDK 11+
    https://www.oracle.com/technetwork/ja
    va/javase/overview/oracle-jdk-faqs.html
    Ограничения новых релизов OpenJDK 8
    от Oracle
    97

    View Slide

  98. © 2019 CloudBees, Inc. All Rights Reserved.
    OpenJDK Jigsaw Team: Собирайте OpenJDK сами
    Мы:
    ● AdoptOpenJDK
    ● RedHat JDK для CentOS
    ● …
    Какой дистрибутив взять?
    98
    https://adoptopenjdk.net/

    View Slide

  99. © 2019 CloudBees, Inc. All Rights Reserved.
    99

    View Slide

  100. © 2019 CloudBees, Inc. All Rights Reserved.
    Jenkins & Docker. Packaging
    https://hub.docker.com/r/jenkins/ AND https://hub.docker.com/r/jenkinsci 100

    View Slide

  101. © 2019 CloudBees, Inc. All Rights Reserved.
    Docker Packaging
    Базовый образ: https://hub.docker.com/_/openjdk/
    101

    View Slide

  102. © 2019 CloudBees, Inc. All Rights Reserved.
    Docker Packaging
    Базовый образ: https://hub.docker.com/_/openjdk/
    ● Поддерживается Docker, не Oracle
    ● Отстает от релизов, особенно для EA
    ● Нет образов для Arm & Co
    ● Не рекомендовано OpenJDK Jigsaw Team
    ● Непонятное будущее
    102

    View Slide

  103. © 2019 CloudBees, Inc. All Rights Reserved.
    Сборка
    Дистрибутивы
    Юнит-тесты
    Статический анализ
    Интеграционные тесты
    103

    View Slide

  104. © 2019 CloudBees, Inc. All Rights Reserved.
    Ожидания
    Image:
    https://www.kdnuggets.com/2016/10/big
    -data-science-expectation-reality.html
    104

    View Slide

  105. © 2019 CloudBees, Inc. All Rights Reserved.
    Ожидания
    Image:
    https://www.kdnuggets.com/2016/10/big
    -data-science-expectation-reality.html
    Реальность
    105

    View Slide

  106. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Jenkins работает на Java 11
    ● TLS 1.3 и улучшения “из коробки”
    ● <1% распространение среди пользователей
    ● Удалили экспериментальные опции (cgroups)
    ● Обновили кодовую базу и зависимости
    Что получили?
    106

    View Slide

  107. © 2019 CloudBees, Inc. All Rights Reserved.
    Чего не хватало?

    Обновлённой Maven-
    экосистемы

    Сканеров совместимости с
    Java 11

    Тулов для “правильного”
    апдейта зависимостей
    107

    View Slide

  108. © 2019 CloudBees, Inc. All Rights Reserved.
    Чего не хватало?

    Обновлённой Maven-
    экосистемы

    Сканеров совместимости с
    Java 11

    Тулов для “правильного”
    апдейта зависимостей
    108

    View Slide

  109. © 2019 CloudBees, Inc. All Rights Reserved.
    ● Java 11 - это серьёзно
    ● Надо пробовать
    ● Миграция возможна
    ● Большая часть времени - CI и автотесты
    ● Апдейт - Отличная возможность
    прочувствовать технический долг
    ● Пробуйте тулы, если они есть
    Takeaways
    109

    View Slide

  110. © 2019 CloudBees, Inc. All Rights Reserved.
    Contacts:
    E-mail: [email protected]
    GitHub: oleg-nenashev
    Twitter: @oleg_nenashev
    ВОПРОСЫ?
    110

    View Slide