blob: cf1892bd556714717993c9bf1860048e54294efb [file] [log] [blame]
<!doctype html><html lang=en class=no-js><head><meta name=ROBOTS content="INDEX, FOLLOW"><link rel=canonical href=https://cn.dubbo.apache.org/en/blog/2018/08/14/native-image-using-graalvm/><script>var _hmt=_hmt||[];(function(){var e,t=document.createElement("script");t.src="https://hm.baidu.com/hm.js?3b78f49ba47181e4d998a66b689446e9",e=document.getElementsByTagName("script")[0],e.parentNode.insertBefore(t,e)})()</script><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta http-equiv=Content-Security-Policy content="frame-src *"><meta name=generator content="Hugo 0.122.0"><link rel="shortcut icon" type=image/png href=/imgs/favicon.png><link rel=apple-touch-icon href=/favicons/apple-touch-icon-180x180.png sizes=180x180><link rel=manifest href=/manifest.webmanifest><title>Native Image using GraalVM | Apache Dubbo</title><meta property="og:title" content="Native Image using GraalVM">
<meta property="og:description" content="This article introduces you how to make Dubbo native image using GraalVM.
"><meta property="og:type" content="article"><meta property="og:url" content="https://cn.dubbo.apache.org/en/blog/2018/08/14/native-image-using-graalvm/"><meta property="article:section" content="blog"><meta property="article:published_time" content="2018-08-14T00:00:00+00:00"><meta property="article:modified_time" content="2023-02-23T11:00:42+08:00"><meta itemprop=name content="Native Image using GraalVM"><meta itemprop=description content="This article introduces you how to make Dubbo native image using GraalVM.
"><meta itemprop=datePublished content="2018-08-14T00:00:00+00:00"><meta itemprop=dateModified content="2023-02-23T11:00:42+08:00"><meta itemprop=wordCount content="1360"><meta itemprop=keywords content><meta name=twitter:card content="summary"><meta name=twitter:title content="Native Image using GraalVM"><meta name=twitter:description content="This article introduces you how to make Dubbo native image using GraalVM.
"><script async src="https://www.googletagmanager.com/gtag/js?id=G-NM6FFMT51J"></script><script>var doNotTrack=!1;if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-NM6FFMT51J",{anonymize_ip:!1})}</script><link rel=preload href=/scss/main.min.f77e221bcdbe0cadb996060fe82063c747b60c229a1f8bbf0ee529adbadd84fa.css as=style><link href=/scss/main.min.f77e221bcdbe0cadb996060fe82063c747b60c229a1f8bbf0ee529adbadd84fa.css rel=stylesheet integrity><script src=/js/jquery-3.5.1.min.js integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin=anonymous></script><meta name=theme-color content="#326ce5"><link rel=stylesheet href=/css/feature-states.css><meta name=description content="This article introduces you how to make Dubbo native image using GraalVM.
"><meta property="og:description" content="This article introduces you how to make Dubbo native image using GraalVM.
"><meta name=twitter:description content="This article introduces you how to make Dubbo native image using GraalVM.
"><meta property="og:url" content="https://cn.dubbo.apache.org/en/blog/2018/08/14/native-image-using-graalvm/"><meta property="og:title" content="Native Image using GraalVM"><meta name=twitter:title content="Native Image using GraalVM"><meta name=twitter:image:alt content="Apache Dubbo"><meta property="og:image" content="/imgs/blog/dubbo-graalvm-support/graalvm_env.png"><meta property="og:type" content="article"><meta name=viewport content="width=device-width"><script async defer src=/js/github-buttons.js></script><link href=/css/community.css rel=stylesheet><link href=/css/contactus.css rel=stylesheet><link href=/css/language.css rel=stylesheet><script src=/js/script.js></script></head><body class="td-page td-documentation"><header><nav class="js-navbar-scroll navbar navbar-expand navbar-dark flex-column flex-md-row td-navbar" data-auto-burger=primary><a class=navbar-brand href=/en/><span class=navbar-logo></span><span class="text-uppercase font-weight-bold">Apache Dubbo</span></a><div class="td-navbar-nav-scroll ml-md-auto" id=main_navbar><ul class="navbar-nav mt-2 mt-lg-0"><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/overview/><span>Overview</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/docs3-v2/><span>SDK Manual</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class="nav-link active" href=/en/blog/><span class=active>Blog</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/download/><span>Download</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=https://start.dubbo.apache.org/bootstrap.html target=_blank><span>Initializer</span><i class='fas fa-external-link-alt'></i></a></li><li class="nav-item dropdown d-lg-block"><a class="nav-link dropdown-toggle" href=# id=navbarDropdownMenuLink role=button data-toggle=dropdown aria-haspopup=true aria-expanded=false>English</a><div class="dropdown-menu dropdown-menu-right" aria-labelledby=navbarDropdownMenuLink><a class=dropdown-item href=/zh-cn/>δΈ­ζ–‡</a></div></li><li class="nav-item dropdown d-lg-block"><div class="nav-item d-none d-lg-block"></div></li></ul></div></nav><section class="header-hero text-white pb-0 light-text"></section></header><div class="container-fluid td-outer"><div class=td-main><div class="row flex-md-nowrap"><div class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"><script>$(function(){$("#td-section-nav a").removeClass("active"),$("#td-section-nav #m-enblog20180814native-image-using-graalvm").addClass("active"),$("#td-section-nav #m-enblog20180814native-image-using-graalvm-li span").addClass("td-sidebar-nav-active-item"),$("#td-section-nav #m-enblog20180814native-image-using-graalvm").parents("li").addClass("active-path"),$("#td-section-nav li.active-path").addClass("show"),$("#td-section-nav li.active-path").children("input").prop("checked",!0),$("#td-section-nav #m-enblog20180814native-image-using-graalvm-li").siblings("li").addClass("show"),$("#td-section-nav #m-enblog20180814native-image-using-graalvm-li").children("ul").children("li").addClass("show"),$("#td-sidebar-menu").toggleClass("d-none")})</script><div id=td-sidebar-menu class="td-sidebar__inner d-none"><div id=content-mobile><form class="td-sidebar__search d-flex align-items-center"><button class="btn btn-link td-sidebar__toggle d-md-none p-0 ml-3 fas fa-bars" type=button data-toggle=collapse data-target=#td-section-nav aria-controls=td-docs-nav aria-expanded=false aria-label="Toggle section navigation"></button></form></div><div id=content-desktop></div><nav class="collapse td-sidebar-nav foldable-nav" id=td-section-nav><ul class="td-sidebar-nav__section pr-md-3 ul-0"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblog-li><ul class=ul-1><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblognews-li><input type=checkbox id=m-enblognews-check>
<label for=m-enblognews-check><a href=/en/blog/news/ title="Articles About Apache Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblognews><span>Articles</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20240131tracing-dubbo-with-opentelemetry-li><input type=checkbox id=m-enblog20240131tracing-dubbo-with-opentelemetry-check>
<label for=m-enblog20240131tracing-dubbo-with-opentelemetry-check><a href=/en/blog/2024/01/31/tracing-dubbo-with-opentelemetry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20240131tracing-dubbo-with-opentelemetry><span>Tracing Dubbo With OpenTelemetry</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-li><input type=checkbox id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-check>
<label for=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-check><a href=/en/blog/2023/10/23/introduction-to-apache-dubbo-plugin-for-intellij-idea/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea><span>Introduction to Apache Dubbo plugin for IntelliJ IDEA</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-li><input type=checkbox id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-check>
<label for=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-check><a href=/en/blog/2023/04/15/advanced-cloud-native-dubbo-3.2-officially-released/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released><span>Advanced cloud native - Dubbo 3.2 officially released</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-li><input type=checkbox id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-check>
<label for=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-check><a href=/en/blog/2022/05/04/how-to-proxy-dubbo-service-in-apache-shenyu-gateway/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway><span>How to proxy Dubbo service in Apache ShenYu Gateway</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-li><input type=checkbox id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-check>
<label for=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-check><a href=/en/blog/2022/01/18/makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix><span>Makes it More Convenient for You to Proxy Dubbo Services in Apache APISIX</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190826service-test-li><input type=checkbox id=m-enblog20190826service-test-check>
<label for=m-enblog20190826service-test-check><a href=/en/blog/2019/08/26/service-test/ title="Dubbo Admin service test" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190826service-test><span>Service test in dubbo admin</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-li><input type=checkbox id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-check>
<label for=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-check><a href=/en/blog/2019/08/11/tracing-dubbo-service-with-apache-skywalking/ title="Tracing Dubbo service with Apache Skywalking" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking><span>Use apache skywalking in dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-li><input type=checkbox id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-check>
<label for=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-check><a href=/en/blog/2019/05/02/dubbo-extensible-mechanism-source-code-analysis-part-2/ title="Dubbo extensible mechanism source code analysis - part 2" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2><span>Dubbo extensible mechanism - part 2</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-li><input type=checkbox id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-check>
<label for=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-check><a href=/en/blog/2019/04/25/dubbo-extensible-mechanism-source-code-analysis-part-1/ title="Dubbo extensible mechanism source code analysis - part 1" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1><span>Dubbo extensible mechanism - part 1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-li><input type=checkbox id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-check>
<label for=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-check><a href=/en/blog/2019/02/20/implementation-background-and-practice-of-dubbo-client-asynchronous-interface/ title="Implementation background and practice of Dubbo client asynchronous interface" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface><span>Dubbo Async Client</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-li><input type=checkbox id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-check>
<label for=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-check><a href=/en/blog/2019/02/20/implementation-background-and-practice-of-dubbo-server-asynchronous-interface/ title="Implementation background and practice of Dubbo server asynchronous interface" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface><span>Dubbo Async Server</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-li><input type=checkbox id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-check>
<label for=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-check><a href=/en/blog/2019/01/17/how-to-use-seata-to-ensure-consistency-between-dubbo-microservices/ title="How to use Seata to ensure consistency between Dubbo Microservices" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices><span>Use Seata in Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-li><input type=checkbox id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-check>
<label for=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-check><a href=/en/blog/2018/12/10/the-fifth-dubbo-meetup-has-been-held-in-hangzhou/ title="The fifth Dubbo meetup has been held in Hangzhou" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou><span>The fifth Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-li><input type=checkbox id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-check>
<label for=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-check><a href=/en/blog/2018/11/07/dubbo-integrates-with-nacos-to-become-a-registry/ title="Dubbo Integrates with Nacos to Become a Registry" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry><span>Use Dubbo with Nacos</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181005introduction-to-the-dubbo-protocol-li><input type=checkbox id=m-enblog20181005introduction-to-the-dubbo-protocol-check>
<label for=m-enblog20181005introduction-to-the-dubbo-protocol-check><a href=/en/blog/2018/10/05/introduction-to-the-dubbo-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181005introduction-to-the-dubbo-protocol><span>Introduction to the Dubbo protocol</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180930integrate-dubbo-with-kubernetes-li><input type=checkbox id=m-enblog20180930integrate-dubbo-with-kubernetes-check>
<label for=m-enblog20180930integrate-dubbo-with-kubernetes-check><a href=/en/blog/2018/09/30/integrate-dubbo-with-kubernetes/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180930integrate-dubbo-with-kubernetes><span>Integrate Dubbo with Kubernetes</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180902how-to-prepare-an-apache-release-li><input type=checkbox id=m-enblog20180902how-to-prepare-an-apache-release-check>
<label for=m-enblog20180902how-to-prepare-an-apache-release-check><a href=/en/blog/2018/09/02/how-to-prepare-an-apache-release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180902how-to-prepare-an-apache-release><span>How to prepare an Apache Release</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-li><input type=checkbox id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-check>
<label for=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-check><a href=/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/ title="How to implement a fully asynchronous calls chain based on Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo><span>New Async Call</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-li><input type=checkbox id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-check>
<label for=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-check><a href=/en/blog/2018/08/26/the-fourth-dubbo-meetup-has-been-held-in-chengdu/ title="The fourth Dubbo meetup has been held in Chengdu" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu><span>The fourth Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-li><input type=checkbox id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-check>
<label for=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-check><a href=/en/blog/2018/08/14/dubbo-basic-usage-dubbo-consumer-configuration/ title=" Dubbo Basic Usage - Dubbo Consumer Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration><span>Dubbo Consumer Configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-li><input type=checkbox id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-check>
<label for=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-check><a href=/en/blog/2018/08/14/dubbo-several-ways-about-synchronous/asynchronous-invoke/ title="Dubbo: Several ways about synchronous/asynchronous invoke" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke><span>Dubbo Invoke</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-li><input type=checkbox id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-check>
<label for=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-check><a href=/en/blog/2018/08/14/dubbo-basic-usage--dubbo-provider-configuration/ title="Dubbo Basic Usage -- Dubbo Provider Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration><span>Dubbo Provider Configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814manipulating-services-dynamically-via-qos-li><input type=checkbox id=m-enblog20180814manipulating-services-dynamically-via-qos-check>
<label for=m-enblog20180814manipulating-services-dynamically-via-qos-check><a href=/en/blog/2018/08/14/manipulating-services-dynamically-via-qos/ title="Manipulating Services Dynamically via QoS" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814manipulating-services-dynamically-via-qos><span>Dubbo QoS Introduction</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-li><input type=checkbox id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-check>
<label for=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-check><a href=/en/blog/2018/08/14/source-code-analysis-of-spring-boot-dubbo-app-start-and-stop/ title="Source code analysis of spring-boot+Dubbo App start and stop" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop><span>Dubbo start/stop in spring boot</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-li><input type=checkbox id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-check>
<label for=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-check><a href=/en/blog/2018/08/14/implementation-of-cross-language-calls-by-dubbo2.js/ title="Implementation of cross-language calls by Dubbo2.js" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js><span>dubbo2.js introduction</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814generic-invoke-of-dubbo-li><input type=checkbox id=m-enblog20180814generic-invoke-of-dubbo-check>
<label for=m-enblog20180814generic-invoke-of-dubbo-check><a href=/en/blog/2018/08/14/generic-invoke-of-dubbo/ title="Generic invoke of Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814generic-invoke-of-dubbo><span>Generic invoke</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814native-image-using-graalvm-li><input type=checkbox id=m-enblog20180814native-image-using-graalvm-check>
<label for=m-enblog20180814native-image-using-graalvm-check><a href=/en/blog/2018/08/14/native-image-using-graalvm/ title="Native Image using GraalVM" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814native-image-using-graalvm><span>Native Image</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180810dubbos-load-balance-li><input type=checkbox id=m-enblog20180810dubbos-load-balance-check>
<label for=m-enblog20180810dubbos-load-balance-check><a href=/en/blog/2018/08/10/dubbos-load-balance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180810dubbos-load-balance><span>Dubbo's Load Balance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807use-annotations-in-dubbo-li><input type=checkbox id=m-enblog20180807use-annotations-in-dubbo-check>
<label for=m-enblog20180807use-annotations-in-dubbo-check><a href=/en/blog/2018/08/07/use-annotations-in-dubbo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807use-annotations-in-dubbo><span>Use Annotations In Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807using-zookeeper-in-dubbo-li><input type=checkbox id=m-enblog20180807using-zookeeper-in-dubbo-check>
<label for=m-enblog20180807using-zookeeper-in-dubbo-check><a href=/en/blog/2018/08/07/using-zookeeper-in-dubbo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807using-zookeeper-in-dubbo><span>Using Zookeeper in Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807dubbo-101-li><input type=checkbox id=m-enblog20180807dubbo-101-check>
<label for=m-enblog20180807dubbo-101-check><a href=/en/blog/2018/08/07/dubbo-101/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807dubbo-101><span>Your First Dubbo Demo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-li><input type=checkbox id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-check>
<label for=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-check><a href=/en/blog/2018/07/30/the-third-dubbo-meetup-has-been-held-in-shenzhen/ title="The third Dubbo meetup has been held in Shenzhen" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen><span>The third Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-li><input type=checkbox id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-check>
<label for=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-check><a href=/en/blog/2018/07/27/sentinel-the-flow-sentinel-of-dubbo-services/ title="Sentinel: The flow sentinel of Dubbo services" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services><span>Introduce sentinel</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180712tracking-with-pinpoint-li><input type=checkbox id=m-enblog20180712tracking-with-pinpoint-check>
<label for=m-enblog20180712tracking-with-pinpoint-check><a href=/en/blog/2018/07/12/tracking-with-pinpoint/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180712tracking-with-pinpoint><span>Tracking with Pinpoint</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180701your-first-dubbo-filter-li><input type=checkbox id=m-enblog20180701your-first-dubbo-filter-check>
<label for=m-enblog20180701your-first-dubbo-filter-check><a href=/en/blog/2018/07/01/your-first-dubbo-filter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180701your-first-dubbo-filter><span>Your First Dubbo Filter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-li><input type=checkbox id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-check>
<label for=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-check><a href=/en/blog/2018/06/23/the-second-dubbo-shanghai-meetup-has-been-held-successfully/ title="The second Dubbo Shanghai meetup has been held successfully" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully><span>The second Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-li><input type=checkbox id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-check>
<label for=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-check><a href=/en/blog/2018/05/12/the-first-dubbo-meetup-has-been-held-in-beijing/ title="The first Dubbo meetup has been held in Beijing" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing><span>The first Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180502the-apachecon-na-schedule-has-been-announced-li><input type=checkbox id=m-enblog20180502the-apachecon-na-schedule-has-been-announced-check>
<label for=m-enblog20180502the-apachecon-na-schedule-has-been-announced-check><a href=/en/blog/2018/05/02/the-apachecon-na-schedule-has-been-announced/ title="The ApacheCon NA schedule has been announced" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180502the-apachecon-na-schedule-has-been-announced><span>ApacheCon NA</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180425the-gsocgoogle-summer-of-code-2018-li><input type=checkbox id=m-enblog20180425the-gsocgoogle-summer-of-code-2018-check>
<label for=m-enblog20180425the-gsocgoogle-summer-of-code-2018-check><a href=/en/blog/2018/04/25/the-gsocgoogle-summer-of-code-2018/ title="The GSoC(Google Summer of Code) 2018" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180425the-gsocgoogle-summer-of-code-2018><span>GSoC 2018</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-li><input type=checkbox id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-check>
<label for=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-check><a href=/en/blog/2018/04/22/dubbo-roadmap-is-announced-in-qcon-beijing-2018/ title="Dubbo roadmap is announced in QCon Beijing 2018" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018><span>QCon Beijing 2018</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblogproposals-li><input type=checkbox id=m-enblogproposals-check>
<label for=m-enblogproposals-check><a href=/en/blog/proposals/ title="Proposals About Apache Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblogproposals><span>Proposals</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog10101application-level-service-discovery-li><input type=checkbox id=m-enblog10101application-level-service-discovery-check>
<label for=m-enblog10101application-level-service-discovery-check><a href=/en/blog/1/01/01/application-level-service-discovery/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog10101application-level-service-discovery><span>Application-Level Service Discovery</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-li><input type=checkbox id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-check>
<label for=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-check><a href=/en/blog/1/01/01/enhanced-http-standard-capabilities-of-triple-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol><span>Enhanced HTTP Standard Capabilities of Triple Protocol</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblogreleases-li><input type=checkbox id=m-enblogreleases-check>
<label for=m-enblogreleases-check><a href=/en/blog/releases/ title="New Releases" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblogreleases><span>Releases</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog202109202714-release-note-li><input type=checkbox id=m-enblog202109202714-release-note-check>
<label for=m-enblog202109202714-release-note-check><a href=/en/blog/2021/09/20/2.7.14-release-note/ title="2.7.14 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog202109202714-release-note><span>2.7.14</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog202108233021-release-note-li><input type=checkbox id=m-enblog202108233021-release-note-check>
<label for=m-enblog202108233021-release-note-check><a href=/en/blog/2021/08/23/3.0.2.1-release-note/ title="3.0.2.1 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog202108233021-release-note><span>3.0.2.1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20210818302-release-note-li><input type=checkbox id=m-enblog20210818302-release-note-check>
<label for=m-enblog20210818302-release-note-check><a href=/en/blog/2021/08/18/3.0.2-release-note/ title="3.0.2 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20210818302-release-note><span>3.0.2</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20210702301-release-note-li><input type=checkbox id=m-enblog20210702301-release-note-check>
<label for=m-enblog20210702301-release-note-check><a href=/en/blog/2021/07/02/3.0.1-release-note/ title="3.0.1 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20210702301-release-note><span>3.0.1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20200518past-releases-li><input type=checkbox id=m-enblog20200518past-releases-check>
<label for=m-enblog20200518past-releases-check><a href=/en/blog/2020/05/18/past-releases/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20200518past-releases><span>Past Releases</span></a></label></li></ul></li></ul></li></ul></nav></div></div><main class="col-12 col-md-9 col-xl-8 pl-md-5" role=main><nav aria-label=breadcrumb class=td-breadcrumbs><ol class=breadcrumb><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/blog/>Blog</a></li><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/blog/news/>Articles</a></li><li class="breadcrumb-item active" aria-current=page><a href=https://cn.dubbo.apache.org/en/blog/2018/08/14/native-image-using-graalvm/ aria-disabled=true class="btn-link disabled">Native Image</a></li></ol></nav><section id=deprecation-warning><div class="content deprecation-warning pageinfo outdated-blog"><p>This article is more than one year old. Older articles may contain outdated content. Check that the information in the page has not become incorrect since its publication.</p></div></section><div class=td-content><h1>Native Image using GraalVM</h1><div class=lead>This article introduces you how to make Dubbo native image using GraalVM.</div><div class="td-byline mb-4"><time datetime=2018-08-14 class=text-muted>Tuesday, August 14, 2018</time></div><header class=article-meta></header><h2 id=overview>Overview</h2><p>This document will show you how to access GraalVM with a dubbo project and how to compile the project to a binary executable using native-image. The document also introduces the efforts we made in achieving this.</p><p>GraalVM&rsquo;s essential is the Graal compiler, an excellent just-in-time (JIT) compiler. It can be used as both a JIT compiler and a static compiler for ahead-of-time compilation. Graal compiler completes the primary compilation work.</p><p>For more information about GraalVM, read <a href=https://www.graalvm.org/docs/getting-started/container-images/>https://www.graalvm.org/docs/getting-started/container-images/</a>.</p><h2 id=preparation>Preparation</h2><p>Before compiling the dubbo project, make sure that we are programming based on the GraalVM environment.</p><p>GraalVM&rsquo;s installation process won&rsquo;t be introduced in this document. You can visit <a href=https://www.graalvm.org/>https://www.graalvm.org/</a> and select the latest version to install. After installation you will be able to see the following in local jdk:</p><p><img src=/imgs/blog/dubbo-graalvm-support/graalvm_env.png alt=graalvm_env.png>
GraalVM we use here is based on jdk version 1.8.</p><h2 id=get-started>Get Started</h2><p>For user&rsquo;s convenience, we provide the following demo in the <a href=https://github.com/apache/dubbo/>apache dubbo</a> branch. In module dubbo-demo-native, dubbo&rsquo;s provider and consumer demos are given:</p><p><img src=/imgs/blog/dubbo-graalvm-support/demo_path.png alt=demo_path.png></p><p>We used native-image&rsquo;s maven plug-in and customized several native-image starting parameters. Users only need to run maven&rsquo;s compile and package command in consumers&rsquo; and providers&rsquo; modules:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>mvn <span style=color:#719e07>-</span>U clean <span style=color:#719e07>package</span> <span style=color:#719e07>-</span>Dmaven.test.skip=<span style=color:#cb4b16>true</span>
</span></span></code></pre></div><p>You can see the following output after compilation:</p><p><img src=/imgs/blog/dubbo-graalvm-support/consumer_compiler.png alt=provider_compiler.png><img src=/imgs/blog/dubbo-graalvm-support/provider_compiler.png alt=img></p><p>Binary executable file generated can be found in the target catalog:</p><p><img src=/imgs/blog/dubbo-graalvm-support/compile_result.png alt=compile_result.png></p><p>Size of the binary executable file is around 40M:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>MacdeMacBook-pro-3:target mac$ du -m demo-native-provider
</span></span><span style=display:flex><span>40 demo-native-provider
</span></span></code></pre></div><p>Note: example above is the service registration and discovery based on zookeeper. Users have to launch a zk locally before executing the binary executable file.</p><p>Launch the binary executable file:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>MacdeMacBook-pro-3:target mac$ ./demo-native-provider
</span></span><span style=display:flex><span>......
</span></span><span style=display:flex><span>INFO: [DUBBO] DubboBootstrap is ready., dubbo version: 2.7.12-SNAPSHOT, current host: 10.220.186.228
</span></span><span style=display:flex><span>Jun 15, 2021 2:29:14 PM org.apache.dubbo.common.logger.jdk.JdkLogger info
</span></span><span style=display:flex><span>INFO: [DUBBO] DubboBootstrap has started., dubbo version: 2.7.12-SNAPSHOT, current host: 10.220.186.228
</span></span><span style=display:flex><span>Jun 15, 2021 2:29:14 PM org.apache.dubbo.common.logger.jdk.JdkLogger info
</span></span><span style=display:flex><span>INFO: [DUBBO] DubboBootstrap awaiting ..., dubbo version: 2.7.12-SNAPSHOT, current host: 10.220.186.228
</span></span></code></pre></div><p>Enter consumer&rsquo;s target catalog and execute the binary executable file:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>MacdeMacBook-pro-3:target mac$ ./demo-native-consumer
</span></span><span style=display:flex><span>Hello dubbo, response from provider: 10.220.186.228:20880
</span></span></code></pre></div><p>All the launches and invokes above finish within one second.</p><h2 id=our-efforts>Our Efforts</h2><h3 id=preparations>Preparations</h3><h4 id=class-initializations-auxiliary-configurations>Class Initialization&rsquo;s Auxiliary Configurations</h4><p>Since native-image is constructed prior to runtime, its construction is dependent on the static analysis of which code is accessible. However, this analysis cannot always fully predict all usages of Java Native Interface (JNI) , reflection, dynamic proxy object or classpath resource. In the format of <code>native-image</code> configuration file, we need to provide the usages whose dynamic functions are not detected.</p><p>Here we add the following to the JVM parameter:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>-agentlib:native-image-agent=config-output-dir=/path/to/config-dir/
</span></span></code></pre></div><p>Parameter above will introduce agent and run the project in the conventional way. Agent will interact with JVM and intercept all invokes that look up classes, methods, fields, resources or request proxy access. Later agent will produce the following files in the specified catalog: <code>jni-config.json</code>, <code>reflect-config.json</code>, <code>proxy-config.json</code> and <code>resource-config.json</code>, etc.</p><p>Copy the files above into project&rsquo;s resource/META-INF/native-image folder. When native-image compiles, operations regarding JNI, reflection, dynamic proxy and resources will be loaded after finding class information from these json files.</p><p>Note: in reality, since agent detects operations while running and not all logic branches can be covered, some classes&rsquo; json info won&rsquo;t be generated. However, native-image compiles all classes. This will lead to unexpected errors. Currently there&rsquo;s no way for users to distinguish which classes&rsquo; information are lacking until the errors are reported. Lacked info has to be added to json files manually.</p><h4 id=import-native-image-plug-in>Import Native-Image Plug-In</h4><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>&lt;plugin&gt;
</span></span><span style=display:flex><span> &lt;groupId&gt;org.graalvm.nativeimage&lt;/groupId&gt;
</span></span><span style=display:flex><span> &lt;artifactId&gt;native-image-maven-plugin&lt;/artifactId&gt;
</span></span><span style=display:flex><span> &lt;version&gt;21.0.0.2&lt;/version&gt;
</span></span><span style=display:flex><span> &lt;executions&gt;
</span></span><span style=display:flex><span> &lt;execution&gt;
</span></span><span style=display:flex><span> &lt;goals&gt;
</span></span><span style=display:flex><span> &lt;goal&gt;native-image&lt;/goal&gt;
</span></span><span style=display:flex><span> &lt;/goals&gt;
</span></span><span style=display:flex><span> &lt;phase&gt;package&lt;/phase&gt;
</span></span><span style=display:flex><span> &lt;/execution&gt;
</span></span><span style=display:flex><span> &lt;/executions&gt;
</span></span><span style=display:flex><span> &lt;configuration&gt;
</span></span><span style=display:flex><span> &lt;skip&gt;false&lt;/skip&gt;
</span></span><span style=display:flex><span> &lt;imageName&gt;demo-native-provider&lt;/imageName&gt;
</span></span><span style=display:flex><span> &lt;mainClass&gt;org.apache.dubbo.demo.graalvm.provider.Application&lt;/mainClass&gt;
</span></span><span style=display:flex><span> &lt;buildArgs&gt;
</span></span><span style=display:flex><span> --no-fallback
</span></span><span style=display:flex><span> --initialize-at-build-time=org.slf4j.MDC
</span></span><span style=display:flex><span> --initialize-at-build-time=org.slf4j.LoggerFactory
</span></span><span style=display:flex><span> --initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder
</span></span><span style=display:flex><span> --initialize-at-build-time=org.apache.log4j.helpers.Loader
</span></span><span style=display:flex><span> --initialize-at-build-time=org.apache.log4j.Logger
</span></span><span style=display:flex><span> --initialize-at-build-time=org.apache.log4j.helpers.LogLog
</span></span><span style=display:flex><span> --initialize-at-build-time=org.apache.log4j.LogManager
</span></span><span style=display:flex><span> --initialize-at-build-time=org.apache.log4j.spi.LoggingEvent
</span></span><span style=display:flex><span> --initialize-at-build-time=org.slf4j.impl.Log4jLoggerFactory
</span></span><span style=display:flex><span> --initialize-at-build-time=org.slf4j.impl.Log4jLoggerAdapter
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.epoll.Epoll
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.epoll.Native
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.epoll.EpollEventArray
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.DefaultFileRegion
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.kqueue.KQueueEventLoop
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.kqueue.Native
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.unix.Errors
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.unix.IovArray
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.unix.Limits
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.util.internal.logging.Log4JLogger
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.unix.Socket
</span></span><span style=display:flex><span> --initialize-at-run-time=io.netty.channel.ChannelHandlerMask
</span></span><span style=display:flex><span> --report-unsupported-elements-at-runtime
</span></span><span style=display:flex><span> --allow-incomplete-classpath
</span></span><span style=display:flex><span> --enable-url-protocols=http
</span></span><span style=display:flex><span> -H:+ReportExceptionStackTraces
</span></span><span style=display:flex><span> &lt;/buildArgs&gt;
</span></span></code></pre></div><p>After importing the plug-in, native-image command can be automatically executed when executing maven commands such as packaging.</p><h4 id=import-generated-spi-dependency-package>Import Generated SPI Dependency Package</h4><p>SPI mode of dubbo grants huge expandability. It depends on some generated code that are adaptive to extensions. These generated code are not supported by binary images. To deal with this problem, we did the following:</p><ul><li>Export generated code</li></ul><p>(Note: here we modified compiler&rsquo;s code in dubbo-common. Detailed explanations will be presented later on.)</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>public Class&lt;?&gt; doCompile(String name, String source) throws Throwable {
</span></span><span style=display:flex><span> System.*out*.println(&#34;---&gt;write code:&#34; + name);
</span></span><span style=display:flex><span> Files.*write*(Paths.*get*(&#34;/tmp/sources/&#34; + name), source.getBytes());
</span></span><span style=display:flex><span> ......
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><ul><li><p>Copy the exported code into dubbo-graalvm module
<img src=/imgs/blog/dubbo-graalvm-support/graalvm.png alt=graalvm.png></p></li><li><p>Import module in new project</p></li></ul><p>pom dependency:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>&lt;dependency&gt;
</span></span><span style=display:flex><span> &lt;groupId&gt;org.apache.dubbo&lt;/groupId&gt;
</span></span><span style=display:flex><span> &lt;artifactId&gt;dubbo-graalvm&lt;/artifactId&gt;
</span></span><span style=display:flex><span> &lt;version&gt;2.7.12-SNAPSHOT&lt;/version&gt;
</span></span><span style=display:flex><span>&lt;/dependency&gt;
</span></span></code></pre></div><p>(Note: dubbo that depends on this branch can directly add dependency. Other versions with new SPI added needs to update by exporting the source code.)</p><p>After importing dependencies, we can directly find classes using class names during the process of doCompiler without dynamically generating code:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>@Override
</span></span><span style=display:flex><span>public Class&lt;?&gt; doCompile(String name, String sourceCode) throws Throwable {
</span></span><span style=display:flex><span> try {
</span></span><span style=display:flex><span> Class&lt;?&gt; res = Class.*forName*(name);
</span></span><span style=display:flex><span> return res;
</span></span><span style=display:flex><span> } catch (Throwable ex) {
</span></span><span style=display:flex><span> //ignore
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> //......
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>At this point, all dependencies required for native-image compilation are completed. Packaging can generate binary executable file.</p><h4 id=modifications-to-dubbo-source-code>Modifications to Dubbo Source Code</h4><p>Branch is named native_dubbo_0611 and modified based on tag version <a href=https://github.com/apache/dubbo/releases/tag/dubbo-2.7.12>dubbo-2.7.12</a>. Here we will explain the major modifications.</p><ul><li>Avoid dynamically generated code</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>//dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java
</span></span><span style=display:flex><span>@Override
</span></span><span style=display:flex><span>public Class&lt;?&gt; doCompile(String name, String source) throws Throwable {
</span></span><span style=display:flex><span> try {
</span></span><span style=display:flex><span> Class&lt;?&gt; res = Class.*forName*(name);
</span></span><span style=display:flex><span> return res;
</span></span><span style=display:flex><span> } catch (Throwable ex) {
</span></span><span style=display:flex><span> //ignore
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> CtClassBuilder builder = new CtClassBuilder();
</span></span><span style=display:flex><span> builder.setClassName(name)
</span></span><span style=display:flex><span> //......
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>//dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
</span></span><span style=display:flex><span>@Override
</span></span><span style=display:flex><span>public Class&lt;?&gt; doCompile(String name, String sourceCode) throws Throwable {
</span></span><span style=display:flex><span> try {
</span></span><span style=display:flex><span> Class&lt;?&gt; res = Class.*forName*(name);
</span></span><span style=display:flex><span> return res;
</span></span><span style=display:flex><span> } catch (Throwable ex) {
</span></span><span style=display:flex><span> //ignore
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> int i = name.lastIndexOf(&#39;.&#39;);
</span></span><span style=display:flex><span> String packageName = i &lt; 0 ? &#34;&#34; : name.substring(0, i);
</span></span><span style=display:flex><span> //......
</span></span></code></pre></div><p>Here we modified dubbo&rsquo;s both compilation methods. When compiling source code, first determine if the class, which is, in fact, the generated code in dubbo-graalvm that we imported, is loaded locally based on all class name reflection. The loaded class will be returned after importing the package. No compilation required.</p><ul><li>Substitute code generation in ExtensionLoader</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>//dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
</span></span><span style=display:flex><span>private Class&lt;?&gt; createAdaptiveExtensionClass() {
</span></span><span style=display:flex><span> try {
</span></span><span style=display:flex><span> Class c = Class.*forName*(generatePackageInfo() + &#34;.&#34; + type.getSimpleName() + &#34;$Adaptive&#34;);
</span></span><span style=display:flex><span> return c;
</span></span><span style=display:flex><span> } catch (Throwable e) {
</span></span><span style=display:flex><span> //ignore
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> String code = new AdaptiveClassCodeGenerator(type,cachedDefaultName).generate();
</span></span><span style=display:flex><span> //......
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>private static final String *CODE_PACKAGE* = &#34;%s&#34;;
</span></span><span style=display:flex><span>private String generatePackageInfo() {
</span></span><span style=display:flex><span> return String.*format*(*CODE_PACKAGE*, type.getPackage().getName());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>ExtensionLoader is the main logic class of the whole extension mechanism. Works such as loading configuration, extension class cache and generating self-adopting objects, are all done in the class.</p><p>getAdaptiveExtension() method automatically creates implementation class String for extension points interface.</p><p>Similar to the first modification mentioned above, since we imported the SPI package, code generation is no longer needed. Requesting local class based on class name will work. Return when the implementation class is found. Notice here that the generated extension class names all end with $Adaptive. When looking for classes, remember to add the suffix.</p><ul><li>Substitute Wrapper&rsquo;s usage in Reference/ServiceConfig</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>//dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
</span></span><span style=display:flex><span>// String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
</span></span><span style=display:flex><span> String[] methods = Arrays.*stream*(interfaceClass.getMethods()).map(it-&gt;it.getName()).toArray(String[]::new);
</span></span><span style=display:flex><span> if (methods.length == 0) {
</span></span><span style=display:flex><span> l*ogger*.warn(&#34;No method found in service interface &#34; + interfaceClass.getName());
</span></span><span style=display:flex><span> map.put(*METHODS_KEY*, *ANY_VALUE*);
</span></span><span style=display:flex><span> //......
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>//dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
</span></span><span style=display:flex><span>// String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
</span></span><span style=display:flex><span> String[] methods = Arrays.*stream*(interfaceClass.getMethods()).map(it-&gt;it.getName()).toArray(String[]::new);
</span></span><span style=display:flex><span> if (methods.length == 0) {
</span></span><span style=display:flex><span> l*ogger*.warn(&#34;No method found in service interface &#34; + interfaceClass.getName());
</span></span><span style=display:flex><span> map.put(*METHODS_KEY*, *ANY_VALUE*);
</span></span><span style=display:flex><span> //......
</span></span></code></pre></div><p>Since Wrapper&rsquo;s getWrapper needs to be dynamically generated, here we substitute it by reflected getMethods.</p><ul><li>Add dubbo-graalvm module</li></ul><p>dubbo-graalvm&rsquo;s uses have been explained previously.</p><ul><li>Substitute fastjson by gson</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-fallback data-lang=fallback><span style=display:flex><span>//dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/InMemoryWritableMetadataService.java
</span></span><span style=display:flex><span>@Override
</span></span><span style=display:flex><span>public void publishServiceDefinition(URL providerUrl) {
</span></span><span style=display:flex><span> try {
</span></span><span style=display:flex><span> if (!ProtocolUtils.*isGeneric*(providerUrl.getParameter(*GENERIC_KEY*))) {
</span></span><span style=display:flex><span> String interfaceName = providerUrl.getParameter(*INTERFACE_KEY*);
</span></span><span style=display:flex><span> if (StringUtils.*isNotEmpty*(interfaceName)) {
</span></span><span style=display:flex><span> Class interfaceClass = Class.*forName*(interfaceName);
</span></span><span style=display:flex><span> ServiceDefinition serviceDefinition = ServiceDefinitionBuilder.*build*(interfaceClass);
</span></span><span style=display:flex><span> String data = new Gson().toJson(serviceDefinition);
</span></span><span style=display:flex><span> serviceDefinitions.put(providerUrl.getServiceKey(), data);
</span></span><span style=display:flex><span> return;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> //......
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>cglib is used in fastjson for dynamic proxy, but native-image does not support cglib. So here we use gson instead.</p><ul><li>Substitute set by list for multiple interface proxy invoke</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-gdscript3 data-lang=gdscript3><span style=display:flex><span><span style=color:#719e07>//</span>dubbo<span style=color:#719e07>-</span>rpc<span style=color:#719e07>/</span>dubbo<span style=color:#719e07>-</span>rpc<span style=color:#719e07>-</span>api<span style=color:#719e07>/</span>src<span style=color:#719e07>/</span>main<span style=color:#719e07>/</span>java<span style=color:#719e07>/</span>org<span style=color:#719e07>/</span>apache<span style=color:#719e07>/</span>dubbo<span style=color:#719e07>/</span>rpc<span style=color:#719e07>/</span>proxy<span style=color:#719e07>/</span>AbstractProxyFactory<span style=color:#719e07>.</span>java
</span></span><span style=display:flex><span>@Override
</span></span><span style=display:flex><span>public <span style=color:#719e07>&lt;</span>T<span style=color:#719e07>&gt;</span> T getProxy(Invoker<span style=color:#719e07>&lt;</span>T<span style=color:#719e07>&gt;</span> invoker, boolean generic) throws RpcException {
</span></span><span style=display:flex><span> List<span style=color:#719e07>&lt;</span>Class<span style=color:#719e07>&lt;</span>?<span style=color:#719e07>&gt;&gt;</span> interfaces <span style=color:#719e07>=</span> new ArrayList<span style=color:#719e07>&lt;&gt;</span>();
</span></span><span style=display:flex><span> <span style=color:#cb4b16>String</span> config <span style=color:#719e07>=</span> invoker<span style=color:#719e07>.</span>getUrl()<span style=color:#719e07>.</span>getParameter(<span style=color:#719e07>*</span>INTERFACES<span style=color:#719e07>*</span>);
</span></span><span style=display:flex><span> <span style=color:#719e07>if</span> (config <span style=color:#719e07>!=</span> null <span style=color:#719e07>&amp;&amp;</span> config<span style=color:#719e07>.</span>length() <span style=color:#719e07>&gt;</span> <span style=color:#2aa198>0</span>) {
</span></span><span style=display:flex><span> <span style=color:#cb4b16>String</span>[] types <span style=color:#719e07>=</span> <span style=color:#719e07>*</span>COMMA_SPLIT_PATTERN<span style=color:#719e07>*.</span>split(config);
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (<span style=color:#cb4b16>String</span> type : types) {
</span></span><span style=display:flex><span> <span style=color:#719e07>//</span> <span style=color:#719e07>*</span>TODO can we <span style=color:#b58900>load</span> successfully <span style=color:#719e07>for</span> a different classloader?<span style=color:#719e07>.*</span>
</span></span><span style=display:flex><span> interfaces<span style=color:#719e07>.</span>add(ReflectUtils<span style=color:#719e07>.*</span>forName<span style=color:#719e07>*</span>(type));
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#719e07>//......</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The service here has multiple interfaces which have to be in order when requesting proxy. Set does not fulfill the requirement so we use ArrayList instead.</p><p>Major modifications to dubbo source code are listed above.</p><ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"><li><a href=/en/blog/2018/08/10/dubbos-load-balance/ aria-label="Previous - Dubbo's Load Balance" class="btn btn-primary"><span class=mr-1>←</span>Previous</a></li><li><a href=/en/blog/2018/08/14/generic-invoke-of-dubbo/ aria-label="Next - Generic invoke of Dubbo" class="btn btn-primary">Next<span class=ml-1>β†’</span></a></li></ul></div><div id=pre-footer><h2>Feedback</h2><p class=feedback--prompt>Was this page helpful?</p><button class="btn btn-primary mb-4 feedback--yes">Yes</button>
<button class="btn btn-primary mb-4 feedback--no">No</button></div><script>const yes=document.querySelector(".feedback--yes"),no=document.querySelector(".feedback--no");document.querySelectorAll(".feedback--link").forEach(e=>{e.href=e.href+window.location.pathname});const sendFeedback=e=>{gtag||console.log("!gtag"),gtag("event","click",{event_category:"Helpful",event_label:window.location.pathname,value:e})},disableButtons=()=>{yes.disabled=!0,yes.classList.add("feedback--button__disabled"),no.disabled=!0,no.classList.add("feedback--button__disabled")};yes.addEventListener("click",()=>{sendFeedback(1),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")}),no.addEventListener("click",()=>{sendFeedback(0),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")})</script></main><div class="d-none d-xl-block col-xl-2 td-toc d-print-none"><div class="td-page-meta ml-2 pb-1 pt-2 mb-0"><a href=https://github.com/apache/dubbo-website/edit/master/content/en/blog/news/dubbo-graalvm-support.md target=_blank><i class="fa fa-edit fa-fw"></i> Edit this page</a>
<a href="https://github.com/apache/dubbo-website/new/master/content/en/blog/news/dubbo-graalvm-support.md?filename=change-me.md&amp;value=---%0Atitle%3A+%22Long+Page+Title%22%0AlinkTitle%3A+%22Short+Nav+Title%22%0Aweight%3A+100%0Adescription%3A+%3E-%0A+++++Page+description+for+heading+and+indexes.%0A---%0A%0A%23%23+Heading%0A%0AEdit+this+template+to+create+your+new+page.%0A%0A%2A+Give+it+a+good+name%2C+ending+in+%60.md%60+-+e.g.+%60getting-started.md%60%0A%2A+Edit+the+%22front+matter%22+section+at+the+top+of+the+page+%28weight+controls+how+its+ordered+amongst+other+pages+in+the+same+directory%3B+lowest+number+first%29.%0A%2A+Add+a+good+commit+message+at+the+bottom+of+the+page+%28%3C80+characters%3B+use+the+extended+description+field+for+more+detail%29.%0A%2A+Create+a+new+branch+so+you+can+preview+your+new+file+and+request+a+review+via+Pull+Request.%0A" target=_blank><i class="fa fa-edit fa-fw"></i> Create child page</a>
<a href="https://github.com/apache/dubbo-website/issues/new?title=Native%20Image%20using%20GraalVM" target=_blank><i class="fab fa-github fa-fw"></i> Create an issue</a>
<a href=https://github.com/apache/dubbo/issues/new target=_blank><i class="fas fa-tasks fa-fw"></i> Create project issue</a></div><nav id=TableOfContents><ul><li><a href=#overview>Overview</a></li><li><a href=#preparation>Preparation</a></li><li><a href=#get-started>Get Started</a></li><li><a href=#our-efforts>Our Efforts</a><ul><li><a href=#preparations>Preparations</a></li></ul></li></ul></nav><div class="taxonomy taxonomy-terms-cloud taxo-tags"><h5 class=taxonomy-title>Tags</h5><ul class=taxonomy-terms><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/ecosystem/ data-taxonomy-term=ecosystem><span class=taxonomy-label>ecosystem</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/news/ data-taxonomy-term=news><span class=taxonomy-label>news</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/opentelemetry/ data-taxonomy-term=opentelemetry><span class=taxonomy-label>OpenTelemetry</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/tracing/ data-taxonomy-term=tracing><span class=taxonomy-label>tracing</span><span class=taxonomy-count>1</span></a></li></ul></div></div></div></div></div><footer class="bg-dark py-5 row d-print-none footer-margin-0"><div class="container-fluid mx-sm-5"><div class=row><div class="col-6 col-sm-4 text-xs-center order-sm-2"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Dubbo mailing list archive" aria-label="Dubbo mailing list archive"><a class=text-white target=_blank rel="noopener noreferrer" href=https://lists.apache.org/list.html?dev@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-6 col-sm-4 text-right text-xs-center order-sm-3"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=GitHub aria-label=GitHub><a class=text-white target=_blank rel="noopener noreferrer" href=https://github.com/apache/dubbo><i class="fab fa-github"></i></a></li><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Subscribe to mailing list" aria-label="Subscribe to mailing list"><a class=text-white target=_blank rel="noopener noreferrer" href=mailto:dev-subscribe@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-12 col-sm-4 text-center py-2 order-sm-2"><small class=text-white>&copy; 2024 The Apache Software Foundation. Apache and the Apache feather logo are trademarks of The Apache Software Foundation. All Rights Reserved</small></div></div></div></footer><div class="row pt-2 pb-2 footer-margin-0"><div class="container-fluid mx-sm-5"><div class=text-center id=my-footer><img alt=apache_logo src=/imgs/apache_logo.png><ul><li><a href=https://www.apache.org>Foundation</a></li><li><a href=https://www.apache.org/licenses/>License</a></li><li><a href=https://dubbo.apache.org/en/overview/notices/>Security</a></li><li><a href=https://www.apache.org/events/current-event>Events</a></li><li><a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a></li><li><a href=https://privacy.apache.org/policies/privacy-policy-public.html>Privacy</a></li><li><a href=https://www.apache.org/foundation/thanks.html>Thanks</a></li></ul></div></div></div><script src=/js/popper.min.js integrity=sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49 crossorigin=anonymous></script><script src=/js/bootstrap.min.js integrity=sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy crossorigin=anonymous></script><script src=/js/main.min.b075178d232d3b0039b3cb6af2fc2e9d90071820167a60f4eea3a79169975ee8.js integrity="sha256-sHUXjSMtOwA5s8tq8vwunZAHGCAWemD07qOnkWmXXug=" crossorigin=anonymous></script><script async src=https://widget.kapa.ai/kapa-widget.bundle.js data-website-id=d763c4f2-f871-400b-aeca-d986c4af73c2 data-project-name="Apache Dubbo" data-project-color=#E8442E data-button-text="Ask AI" data-search-mode-enabled=true data-modal-open-on-command-k=true data-modal-disclaimer="The AI supports multiple languages, but it may not be accessible in China due to recaptcha, a proxy is required." data-project-logo=https://pbs.twimg.com/profile_images/1011849068283191302/FJbH5vbF_400x400.jpg data-modal-example-questions="What is Apache Dubbo?,How to run Apache Dubbo?" data-button-position-top data-button-position-right=20px data-button-position-bottom=200px data-button-position-left></script><script>(function(e,t,n,s){e[s]=e[s]||[];var a=t.getElementsByTagName(n)[0],i=t.createElement(n);i.async=!0,i.id="beacon-aplus",i.setAttribute("exparams","userid=&aplus&sidx=aplusSidex&ckx=aplusCkx"),i.src="//g.alicdn.com/alilog/mlog/aplus_v2.js",i.crossorigin="anonymous",a.parentNode.insertBefore(i,a)})(window,document,"script","aplus_queue"),function(e){var t=e.createElement("script");t.type="text/javascript",t.async=!0,t.src="//g.alicdn.com/aes/??tracker/3.3.4/index.js,tracker-plugin-pv/3.0.5/index.js,tracker-plugin-event/3.0.0/index.js,tracker-plugin-autolog/3.0.3/index.js,tracker-plugin-survey/3.0.3/index.js,tracker-plugin-jserror/3.0.3/index.js,tracker-plugin-resourceError/3.0.3/index.js",t.onload=function(){window.AES_CONFIG=window.AES_CONFIG||{env:"prod"},window.aes=new AES({pid:"zN245h",user_type:6}),window.AESPluginAutologConfig={exposure:"auto"},window.AEMPluginInstances=[aes.use(AESPluginPV,window.AESPluginPVConfig||{enableHistory:!0}),aes.use(AESPluginEvent,window.AESPluginEventConfig||{}),aes.use(AESPluginSurvey,window.AESPluginEventConfig||{}),aes.use(AESPluginAutolog,window.AESPluginAutologConfig||{}),aes.use(AESPluginJSError,window.AESPluginJSError||{}),aes.use(AESPluginResourceError,window.AESPluginResourceError||{})]},setTimeout(function(){e.getElementsByTagName("body")[0].appendChild(t)},800)}(document)</script></body></html>