{"id":281546,"date":"2016-11-25T12:50:04","date_gmt":"2016-11-25T09:50:04","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=281546"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=281546","title":{"rendered":"\u041b\u0443\u0447\u0448\u0435 \u0432 \u0440\u0430\u0439\u043d\u0442\u0430\u0439\u043c\u0435, \u0447\u0435\u043c \u043d\u0438\u043a\u043e\u0433\u0434\u0430: \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c API JIRA \u00ab\u043d\u0430 \u043b\u0435\u0442\u0443\u00bb"},"content":{"rendered":"<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 API \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u043d\u0435\u0442?<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/2fa\/67d\/0e1\/2fa67d0e1abc455385d45f4e5db19e64.jpg\"\/><\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043d\u0430\u0434\u0435\u0436\u0434\u043e\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043f\u0430\u043a\u0435\u0442\u0430 <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/package-summary.html\">java.lang.instrument<\/a>. \u0412\u0441\u0435\u043c, \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0447\u0442\u043e \u0438 \u043a\u0430\u043a \u0432 Java \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043a\u043e\u0434\u043e\u043c \u0432 \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0439 VM, \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u041d\u0430 \u0425\u0430\u0431\u0440\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u0438 \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u0430\u0439\u0442\u043a\u043e\u0434\u043e\u043c:<\/p>\n<ul>\n<li><a href=\"https:\/\/habrahabr.ru\/post\/230239\/\">Java Agent \u043d\u0430 \u0441\u043b\u0443\u0436\u0431\u0435 JVM<\/a><\/li>\n<li><a href=\"https:\/\/habrahabr.ru\/company\/yandex\/blog\/280117\/\">\u0422\u0435\u043e\u0440\u0438\u044f \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 AOP. \u041a\u0430\u043a \u043c\u044b \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u0432 \u042f\u043d\u0434\u0435\u043a\u0441\u0435<\/a><\/li>\n<li><a href=\"https:\/\/habrahabr.ru\/post\/254791\/\">\u0410\u0441\u043f\u0435\u043a\u0442\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435. \u041e\u0441\u043d\u043e\u0432\u044b<\/a><\/li>\n<\/ul>\n<p>  \u041d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u0410 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u043c\u0430\u0445\u043d\u0443\u0442\u044c\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438? <\/p>\n<p>  \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f java \u0430\u0433\u0435\u043d\u0442\u0430 (\u0438 <a href=\"https:\/\/www.osgi.org\/\"><abbr title=\"Open Service Gateway interface\">OSGi<\/abbr><\/a>, \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Byte Buddy), \u0441 \u0446\u0435\u043b\u044c\u044e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0421\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430 \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u043b\u044e\u0434\u044f\u043c, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c \u0441 JIRA, \u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d \u0438 \u043a \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c.<\/p>\n<h3><font color=\"#9cc2ce\">\u0417\u0430\u0434\u0430\u0447\u0430<\/font><\/h3>\n<p>  \u0418\u0442\u0430\u043a, \u043f\u043e\u0441\u043b\u0435 \u0434\u0432\u0443\u0445-\u0442\u0440\u0435\u0445 \u0434\u043d\u0435\u0439 \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f API JIRA \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c, \u0447\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u043e\u0441\u0441-\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u0435\u0439(\u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043f\u043e\u043b\u044f) \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438\/\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043d\u0438\u043a\u0430\u043a \u043a\u0440\u043e\u043c\u0435 \u043a\u0430\u043a \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/answers.atlassian.com\/questions\/125775\/how-can-i-make-fields-required-on-a-transition-screen-but-not-required-on-the-edit-screen\">\u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0430<\/a>. \u041f\u043e\u0434\u0445\u043e\u0434 \u0440\u0430\u0431\u043e\u0447\u0438\u0439, \u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0438 \u043d\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0440\u0435\u043c\u044f \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u043f\u043b\u0430\u043d \u0411.<\/p>\n<p>  \u041d\u0430 \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u043c <a href=\"http:\/\/jokerconf.com\/\">\u0414\u0436\u043e\u043a\u0435\u0440\u0435<\/a> \u0431\u044b\u043b <a href=\"http:\/\/jokerconf.com\/talks\/making-java-more-dynamic\/\">\u0434\u043e\u043a\u043b\u0430\u0434<\/a> <a href=\"https:\/\/twitter.com\/rafaelcodes\">Rafael Winterhalter<\/a> \u043f\u0440\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"http:\/\/bytebuddy.net\/\">Byte Buddy<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u043e\u0449\u043d\u044b\u0439 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 API \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0430\u0439\u0442-\u043a\u043e\u0434\u0430 \u0432 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0443\u044e \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0443. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443\u0436\u0435 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u0430, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u0441 \u043d\u0435\u0434\u0430\u0432\u043d\u0438\u0445 \u043f\u043e\u0440 \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 <a href=\"http:\/\/site.mockito.org\/\">Mockito<\/a> \u0438 <a href=\"http:\/\/jug.ru\/2016\/11\/hibernate-switches-to-byte-buddy\/\">Hibernate<\/a>. \u0421\u0440\u0435\u0434\u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u0420\u0430\u0444\u0430\u044d\u043b\u044c \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Byte Buddy \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432. <\/p>\n<p>  \u0414\u0443\u043c\u0430\u0435\u043c \u00ab\u0410 \u044d\u0442\u043e \u043c\u044b\u0441\u043b\u044c!\u00bb, \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<h3><font color=\"#9cc2ce\">\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/font><\/h3>\n<p>  \u041f\u0435\u0440\u0432\u043e\u0435, \u0438\u0437 \u0434\u043e\u043a\u043b\u0430\u0434\u0430 \u0420\u0430\u0444\u0430\u044d\u043b\u044f \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0430\u0435\u043c, \u0447\u0442\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/Instrumentation.html\">java.lang.instrument.Instrumentation<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 java \u0430\u0433\u0435\u043d\u0442\u0430. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d \u043b\u0438\u0431\u043e \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 VM \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u043b\u0438\u0431\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"http:\/\/docs.oracle.com\/javase\/8\/docs\/technotes\/guides\/attach\/\">Attach API<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 JDK. <\/p>\n<p>  <i>\u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u0430\u044f \u0434\u0435\u0442\u0430\u043b\u044c \u2014 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0430\u0433\u0435\u043d\u0442 \u043d\u0435\u043b\u044c\u0437\u044f \u2014 \u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u044b \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0434\u043e \u043a\u043e\u043d\u0446\u0430 \u0440\u0430\u0431\u043e\u0442\u044b VM.<\/i><\/p>\n<p>  \u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f JIRA \u0432 \u043f\u043b\u0430\u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 attach API, \u0442\u043e \u0442\u0443\u0442 \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u043d\u0430 JDK \u0438 \u0443\u0436 \u0442\u0435\u043c \u0431\u043e\u043b\u0435\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c OS, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430. <br \/>  \u0412\u0442\u043e\u0440\u043e\u0435, \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c, \u0447\u0442\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0435\u0434\u0438\u043d\u0438\u0446\u0435\u0439 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 JIRA \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"https:\/\/developer.atlassian.com\/jiradev\/jira-platform\/building-jira-add-ons\">add-on<\/a> \u2014 <a href=\"https:\/\/osgi.org\/javadoc\/r4v43\/core\/org\/osgi\/framework\/Bundle.html\">Bundle<\/a> \u043d\u0430 \u0441\u0442\u0435\u0440\u043e\u0438\u0434\u0430\u0445. \u0417\u043d\u0430\u0447\u0438\u0442 \u0432\u0441\u044e \u043d\u0430\u0448\u0443 \u043b\u043e\u0433\u0438\u043a\u0443, \u043a\u0430\u043a\u043e\u0439 \u0431\u044b \u043e\u043d\u0430 \u043d\u0438 \u0431\u044b\u043b\u0430, \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 add-on&#8217;\u043e\u0432. \u041e\u0442\u0441\u044e\u0434\u0430 \u0432\u044b\u0442\u0435\u043a\u0430\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0438 \u0431\u0443\u0434\u0435\u043c \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u2014 \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u044b\u043c\u0438 \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u043c\u0438.<\/p>\n<p>  \u0421 \u0443\u0447\u0435\u0442\u043e\u043c \u044d\u0442\u0438\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0432\u0438\u0434\u0438\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e 2 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<ul>\n<li>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0430\u0433\u0435\u043d\u0442\u0430: \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0438 \u0430\u0434\u0434\u043e\u043d\u0430, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u0449\u0438\u0442\u0443 \u043e\u0442 \u0434\u0432\u043e\u0439\u043d\u043e\u0439 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0438, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044e \u0430\u0433\u0435\u043d\u0442\u0430 \u043d\u0430 Linux \u0438 Windows, \u043d\u0430 JDK \u0438 JRE.<br \/>  \u0422.\u043a. \u0430\u0433\u0435\u043d\u0442 \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c, \u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u2014 \u044d\u0442\u043e \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e OSGi. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0434\u043e \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0430\u0433\u0435\u043d\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0435\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u043b\u0430 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0436\u0435.\n<\/li>\n<li>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438: \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0438 \u0430\u0434\u0434\u043e\u043d\u0430, \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0434\u043e\u043b\u0436\u043d\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438.<\/li>\n<\/ul>\n<p>  \u041f\u0440\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f \u0441\u0445\u0435\u043c\u0430:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/a05\/0e6\/6e2\/a050e66e2a9642ac816f4c6fd7aef2a8.png\" \/><\/div>\n<p>  <\/p>\n<h3><font color=\"#9cc2ce\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/font><\/h3>\n<p>  <\/p>\n<h4>\u0410\u0433\u0435\u043d\u0442<\/h4>\n<p>  \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0430\u0433\u0435\u043d\u0442:<\/p>\n<pre><code class=\"java\">public class InstrumentationSupplierAgent {     public static volatile Instrumentation instrumentation;     public static void agentmain(String args, Instrumentation inst) throws Exception {         System.out.println(&quot;==**agent started**==&quot;);         InstrumentationSupplierAgent.instrumentation = inst;         System.out.println(&quot;==**agent execution complete**==&quot;);     } }<\/code><\/pre>\n<p>  \u041a\u043e\u0434 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0439, \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f, \u0434\u0443\u043c\u0430\u044e, \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. \u041a\u0430\u043a \u0438 \u0434\u043e\u0433\u043e\u0432\u0430\u0440\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u2014 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043e\u0431\u0449\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430, \u0432\u0440\u044f\u0434 \u043b\u0438 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c.<\/p>\n<h4>\u041f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c add-on, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u044d\u0442\u043e\u0442 \u0430\u0433\u0435\u043d\u0442 \u0430\u0442\u0442\u0430\u0447\u0438\u0442\u044c \u0432 \u0446\u0435\u043b\u0435\u0432\u0443\u044e VM. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043b\u043e\u0433\u0438\u043a\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0433\u0435\u043d\u0442\u0430. \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0449\u0438\u043a\u0430 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">AgentInstaller.java<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"java\">@Component public class AgentInstaller {      private static final Logger log = LoggerFactory.getLogger(AgentInstaller.class);     private final JiraHome jiraHome;     private final JiraProperties jiraProperties;      @Autowired     public AgentInstaller(         @ComponentImport JiraHome jiraHome,         @ComponentImport JiraProperties jiraProperties     ) {         this.jiraHome = jiraHome;         this.jiraProperties = jiraProperties;     }      private static File getInstrumentationDirectory(JiraHome jiraHome) throws IOException {         final File dataDirectory = jiraHome.getDataDirectory();         final File instrFolder = new File(dataDirectory, &quot;instrumentation&quot;);         if (!instrFolder.exists()) {             Files.createDirectory(instrFolder.toPath());         }         return instrFolder;     }      private static File loadFileFromCurrentJar(File destination, String fileName) throws IOException {         try (InputStream resourceAsStream = AgentInstaller.class.getResourceAsStream(&quot;\/lib\/&quot; + fileName)) {             final File existingFile = new File(destination, fileName);             if (!existingFile.exists() || !isCheckSumEqual(new FileInputStream(existingFile), resourceAsStream)) {                 Files.deleteIfExists(existingFile.toPath());                 existingFile.createNewFile();                 try (OutputStream os = new FileOutputStream(existingFile)) {                     IOUtils.copy(resourceAsStream, os);                 }             }             return existingFile;         }     }      private static boolean isCheckSumEqual(InputStream existingFileStream, InputStream newFileStream) {         try (InputStream oldIs = existingFileStream; InputStream newIs = newFileStream) {             return Arrays.equals(getMDFiveDigest(oldIs), getMDFiveDigest(newIs));         } catch (NoSuchAlgorithmException | IOException e) {             log.error(&quot;Error to compare checksum for streams {},{}&quot;, existingFileStream, newFileStream);             return false;         }     }      private static byte[] getMDFiveDigest(InputStream is) throws IOException, NoSuchAlgorithmException {         final MessageDigest md = MessageDigest.getInstance(&quot;MD5&quot;);         md.digest(IOUtils.toByteArray(is));         return md.digest();     }      public void install() throws PluginException {         try {             log.trace(&quot;Trying to install tools and agent&quot;);             if (!isProperAgentLoaded()) {                 log.info(&quot;Instrumentation agent is not installed yet or has wrong version&quot;);                 final String pid = getPid();                 log.debug(&quot;Current VM PID={}&quot;, pid);                 final URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();                 log.debug(&quot;System classLoader={}&quot;, systemClassLoader);                 final Class&lt;?&gt; virtualMachine = getVirtualMachineClass(                     systemClassLoader,                     &quot;com.sun.tools.attach.VirtualMachine&quot;,                     true                 );                 log.debug(&quot;VM class={}&quot;, virtualMachine);                 Method attach = virtualMachine.getMethod(&quot;attach&quot;, String.class);                 Method loadAgent = virtualMachine.getMethod(&quot;loadAgent&quot;, String.class);                 Method detach = virtualMachine.getMethod(&quot;detach&quot;);                 Object vm = null;                 try {                     log.trace(&quot;Attaching to VM with PID={}&quot;, pid);                     vm = attach.invoke(null, pid);                     final File agentFile = getAgentFile();                     log.debug(&quot;Agent file: {}&quot;, agentFile);                     loadAgent.invoke(vm, agentFile.getAbsolutePath());                 } finally {                     tryToDetach(vm, detach);                 }             } else {                 log.info(&quot;Instrumentation agent is already installed&quot;);             }         } catch (Exception e) {             throw new IllegalPluginStateException(&quot;Failed to load: agent and tools are not installed properly&quot;, e);         }     }      private boolean isProperAgentLoaded() {         try { ClassLoader.getSystemClassLoader().loadClass(InstrumentationProvider.INSTRUMENTATION_CLASS_NAME);             return true;         } catch (Exception e) {             return false;         }     }      private void tryToDetach(Object vm, Method detach) {         try {             if (vm != null) {                 log.trace(&quot;Detaching from VM: {}&quot;, vm);                 detach.invoke(vm);             } else {                 log.warn(&quot;Failed to detach, vm is null&quot;);             }         } catch (Exception e) {             log.warn(&quot;Failed to detach&quot;, e);         }     }      private String getPid() {         String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();         return nameOfRunningVM.split(&quot;@&quot;, 2)[0];     }      private Class&lt;?&gt; getVirtualMachineClass(URLClassLoader systemClassLoader, String className, boolean tryLoadTools) throws Exception {         log.trace(&quot;Trying to get VM class, loadingTools={}&quot;, tryLoadTools);         try {             return systemClassLoader.loadClass(className);         } catch (ClassNotFoundException e) {             if (tryLoadTools) {                 final OS os = getRunningOs();                 os.tryToLoadTools(systemClassLoader, jiraHome);                 return getVirtualMachineClass(systemClassLoader, className, false);             } else {                 throw new ReflectiveOperationException(&quot;Failed to load VM class&quot;, e);             }         }     }      private OS getRunningOs() {         final String osName = jiraProperties.getSanitisedProperties().get(&quot;os.name&quot;);         log.debug(&quot;OS name: {}&quot;, osName);         if (Pattern.compile(&quot;.*[Ll]inux.*&quot;).matcher(osName).matches()) {             return OS.LINUX;         } else if (Pattern.compile(&quot;.*[Ww]indows.*&quot;).matcher(osName).matches()) {             return OS.WINDOWS;         } else {             throw new IllegalStateException(&quot;Unknown OS running&quot;);         }     }      private File getAgentFile() throws IOException {         final File agent = loadFileFromCurrentJar(getInstrumentationDirectory(jiraHome), &quot;instrumentation-agent.jar&quot;);         agent.deleteOnExit();         return agent;     }      private enum OS {         WINDOWS {              @Override             protected String getToolsFilename() {                 return &quot;tools-windows.jar&quot;;             }              @Override             protected String getAttachLibFilename() {                 return &quot;attach.dll&quot;;             }         },         LINUX {              @Override             protected String getToolsFilename() {                 return &quot;tools-linux.jar&quot;;             }              @Override             protected String getAttachLibFilename() {                 return &quot;libattach.so&quot;;             }         };          public void tryToLoadTools(URLClassLoader systemClassLoader, JiraHome jiraHome) throws Exception {             log.trace(&quot;Trying to load tools&quot;);             final File instrumentationDirectory = getInstrumentationDirectory(jiraHome);             appendLibPath(instrumentationDirectory.getAbsolutePath());             loadFileFromCurrentJar(instrumentationDirectory, getAttachLibFilename());             resetCache();             final File tools = loadFileFromCurrentJar(instrumentationDirectory, getToolsFilename());             final Method method = URLClassLoader.class.getDeclaredMethod(&quot;addURL&quot;, URL.class);             method.setAccessible(true);             method.invoke(systemClassLoader, tools.toURI().toURL());         }          private void resetCache() throws NoSuchFieldException, IllegalAccessException {             Field fieldSysPath = ClassLoader.class.getDeclaredField(&quot;sys_paths&quot;);             fieldSysPath.setAccessible(true);             fieldSysPath.set(null, null);         }          private void appendLibPath(String instrumentationDirectory) {             if (System.getProperty(&quot;java.library.path&quot;) != null) {                 System.setProperty(&quot;java.library.path&quot;,                     System.getProperty(&quot;java.library.path&quot;) + System.getProperty(&quot;path.separator&quot;)                         + instrumentationDirectory);             } else {                 System.setProperty(&quot;java.library.path&quot;, instrumentationDirectory);             }         }         protected abstract String getToolsFilename();         protected abstract String getAttachLibFilename();     } }<\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u043e\u0434 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c.<\/p>\n<p>  \u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u2014 \u0435\u0441\u043b\u0438 \u0430\u0433\u0435\u043d\u0442 \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d. \u041c\u043e\u0436\u0435\u0442, \u0435\u0433\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435, \u0430 \u043c\u043e\u0436\u0435\u0442, add-on \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0435 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437.<\/p>\n<p>  \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u2014 \u043b\u0435\u0433\u043a\u043e, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0430\u0433\u0435\u043d\u0442\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440\u043e\u043c<\/p>\n<pre><code class=\"java\">private boolean isProperAgentLoaded() {     try {         ClassLoader.getSystemClassLoader().loadClass(InstrumentationProvider.INSTRUMENTATION_CLASS_NAME);             return true;         } catch (Exception e) {             return false;         }     }<\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u043e\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u043e. \u041d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0443 \u043d\u0430\u0441 \u043f\u0435\u0440\u0432\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430, \u0438 \u0430\u0433\u0435\u043d\u0442 \u0435\u0449\u0435 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u2014 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0441\u0430\u043c\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e attach API. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u044e \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u2014 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043b\u0438 \u043c\u044b \u043f\u043e\u0434 JDK, \u0442.\u0435. \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b\u0439 API \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0438\u043b\u0438 \u043d\u0435\u0442. \u0415\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u00ab\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c\u00bb API.<\/p>\n<pre><code class=\"java\">private Class&lt;?&gt; getVirtualMachineClass(URLClassLoader systemClassLoader, String className, boolean tryLoadTools) throws Exception {         log.trace(&quot;Trying to get VM class, loadingTools={}&quot;, tryLoadTools);         try {             return systemClassLoader.loadClass(className);         } catch (ClassNotFoundException e) {             if (tryLoadTools) {                 final OS os = getRunningOs();                 os.tryToLoadTools(systemClassLoader, jiraHome);                 return getVirtualMachineClass(systemClassLoader, className, false);             } else {                 throw new ReflectiveOperationException(&quot;Failed to load VM class&quot;, e);             }         } }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 attach API. \u0417\u0430\u0434\u0430\u0447\u0430 \u00ab\u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f\u00bb JRE \u0432 JDK \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u043e\u0439 \u041e\u0421. \u0412 JIRA \u043a\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u041e\u0421 \u0443\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d:<\/p>\n<pre><code class=\"java\">private OS getRunningOs() {         final String osName = jiraProperties.getSanitisedProperties().get(&quot;os.name&quot;);         log.debug(&quot;OS name: {}&quot;, osName);         if (Pattern.compile(&quot;.*[Ll]inux.*&quot;).matcher(osName).matches()) {             return OS.LINUX;         } else if (Pattern.compile(&quot;.*[Ww]indows.*&quot;).matcher(osName).matches()) {             return OS.WINDOWS;         } else {             throw new IllegalStateException(&quot;Unknown OS running&quot;);         } }<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u0437\u043d\u0430\u044f \u043f\u043e\u0434 \u043a\u0430\u043a\u043e\u0439 \u043c\u044b \u041e\u0421, \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c attach API. \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u0438\u0437 \u0447\u0435\u0433\u043e \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e <a href=\"http:\/\/www.oracle.com\/technetwork\/java\/javase\/jrereadme-182762.html\">\u0441\u043e\u0441\u0442\u043e\u0438\u0442 attach API<\/a>. \u041a\u0430\u043a \u044f \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u043b \u043e\u043d \u2014 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0439. <\/p>\n<p>  <i>\u0417\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u0435: tools.jar \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u0430\u043a \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0439, \u043d\u043e \u044d\u0442\u043e \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0442\u0430\u043a. \u0412 META-INF\/services\/ \u0435\u0433\u043e \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b com.sun.tools.attach.spi.AttachProvider, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u044b \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u044b:<\/i><\/p>\n<blockquote><p>#[solaris]sun.tools.attach.SolarisAttachProvider<br \/>  #[windows]sun.tools.attach.WindowsAttachProvider<br \/>  #[linux]sun.tools.attach.LinuxAttachProvider<br \/>  #[macosx]sun.tools.attach.BsdAttachProvider<br \/>  #[aix]sun.tools.attach.AixAttachProvider<\/p><\/blockquote>\n<p>  \u041e\u043d\u0438, \u0432 \u0441\u0432\u043e\u044e, \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u0430\u043a \u0440\u0430\u0437 \u043e\u0447\u0435\u043d\u044c \u0434\u0430\u0436\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 \u0441\u0431\u043e\u0440\u043a\u0443 \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0442\u0430\u0449\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u043a\u043e\u043f\u0438\u0438 tools.jar \u0438\u0437 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u043e\u0432 JDK \u0438 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0438\u0445 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<br \/>  \u0427\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0442\u0430\u043a \u044d\u0442\u043e \u0442\u043e, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0444\u0430\u0439\u043b\u044b attach API \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 add-on \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c, \u0442\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438\u0437 jar \u043d\u0435 \u043d\u0430\u0434\u043e \u2014 \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0438\u0437 \u043d\u0430\u0448\u0435\u0433\u043e jar \u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0435 \u043d\u0430\u043c \u0438\u0437 JIRA \u0442\u0438\u0445\u043e\u0435, \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<pre><code class=\"java\">public void tryToLoadTools(URLClassLoader systemClassLoader, JiraHome jiraHome) throws Exception {             log.trace(&quot;Trying to load tools&quot;);             final File instrumentationDirectory = getInstrumentationDirectory(jiraHome);\/\/{JIRA_HOME}\/data\/instrumentation             loadFileFromCurrentJar(instrumentationDirectory, getAttachLibFilename());\/\/\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u0444\u0430\u0439\u043b \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438             final File tools = loadFileFromCurrentJar(instrumentationDirectory, getToolsFilename());\/\/\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c tools.jar             ... }<\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<pre><code class=\"java\">private static File loadFileFromCurrentJar(File destination, String fileName) throws IOException {         try (InputStream resourceAsStream = AgentInstaller.class.getResourceAsStream(&quot;\/lib\/&quot; + fileName)) {             final File existingFile = new File(destination, fileName);             if (!existingFile.exists() || !isCheckSumEqual(new FileInputStream(existingFile), resourceAsStream)) {                 Files.deleteIfExists(existingFile.toPath());\/\/\u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d - \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435                 existingFile.createNewFile();                 try (OutputStream os = new FileOutputStream(existingFile)) {                     IOUtils.copy(resourceAsStream, os);                 }             }             return existingFile;         } }<\/code><\/pre>\n<p>  \u041a\u0440\u043e\u043c\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0445 \u0441\u0443\u043c\u043c. \u041d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043f\u0435\u0440\u0432\u044b\u043c \u043f\u0440\u0438\u0448\u0435\u043b \u043c\u043d\u0435 \u0432 \u0433\u043e\u043b\u043e\u0432\u0443. \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435 \u043c\u043e\u0436\u043d\u043e \u0441 \u0442\u0435\u043c \u0436\u0435 \u0443\u0441\u043f\u0435\u0445\u043e\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432\u0435\u0440\u0441\u0438\u0438, \u0435\u0441\u043b\u0438 \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b. \u0415\u0441\u043b\u0438 \u0444\u0430\u0439\u043b\u044b \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u044b, \u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c\u043d\u044b\u0435 \u0441\u0443\u043c\u043c\u044b \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u0441 \u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u0430\u043c\u0438 \u0438\u0437 \u0430\u0440\u0445\u0438\u0432\u0430, \u043c\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0438\u0445 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c.<\/p>\n<p>  \u0418\u0442\u0430\u043a, \u0444\u0430\u0439\u043b\u044b \u0435\u0441\u0442\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c\u0441\u044f \u043a\u0430\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e \u2014 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0415\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0432 \u043d\u0435\u0434\u0440\u0430 attach API, \u0442\u043e \u0443\u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430:<\/p>\n<pre><code class=\"java\">static {         System.loadLibrary(&quot;attach&quot;); }<\/code><\/pre>\n<p>  \u042d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 \u00abjava.library.path\u00bb<\/p>\n<pre><code class=\"java\">private void appendLibPath(String instrumentationDirectory) {             if (System.getProperty(&quot;java.library.path&quot;) != null) {                 System.setProperty(&quot;java.library.path&quot;,                     System.getProperty(&quot;java.library.path&quot;) + System.getProperty(&quot;path.separator&quot;)                         + instrumentationDirectory);             } else {                 System.setProperty(&quot;java.library.path&quot;, instrumentationDirectory);             } }<\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0438\u0438\u2026 \u0437\u0430\u0431\u0438\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u043a\u043e\u0441\u0442\u044b\u043b\u044c \u0432 \u043d\u0430\u0448\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u00abjava.library.path\u00bb \u043a\u044d\u0448\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 ClassLoader, \u0432 private static String sys_paths[]. \u041d\u0443 \u0447\u0442\u043e \u043d\u0430\u043c private \u2014 \u0438\u0434\u0435\u043c \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u044d\u0448\u2026<\/p>\n<pre><code class=\"java\">private void resetCache() throws NoSuchFieldException, IllegalAccessException {             Field fieldSysPath = ClassLoader.class.getDeclaredField(&quot;sys_paths&quot;);             fieldSysPath.setAccessible(true);             fieldSysPath.set(null, null); }<\/code><\/pre>\n<p>  \u0412\u043e\u0442, \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043c\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438 \u2014 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0447\u0430\u0441\u0442\u0438 API \u043d\u0430 Java. tools.jar \u0432 JDK \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u043c. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0442\u043e\u0433\u043e \u0436\u0435.<\/p>\n<p>  \u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0435\u0431\u0430\u0436\u0438\u0432, \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 java.net.URLClassLoader.<br \/>  \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u044d\u0442\u043e\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a \u0445\u0440\u0430\u043d\u0438\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043a\u0430\u043a \u0441\u043f\u0438\u0441\u043e\u043a URL. \u0412\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c URL \u043d\u0430\u0448\u0435\u0433\u043e tools-[OS].jar \u0432 \u044d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a. \u0418\u0437\u0443\u0447\u0438\u0432 API URLClassLoader&#8217;\u0430 \u043e\u0433\u043e\u0440\u0447\u0430\u0435\u043c\u0441\u044f \u0435\u0449\u0435 \u0440\u0430\u0437, \u0442.\u043a. \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0432\u0430\u0435\u043c, \u0447\u0442\u043e \u043c\u0435\u0442\u043e\u0434 addURL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e, \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f protected. \u042d\u0445\u2026 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043f\u043e\u0434\u043f\u043e\u0440\u043a\u0430 \u043a \u0441\u0442\u0440\u043e\u0439\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0443:<\/p>\n<pre><code class=\"java\">final Method method = URLClassLoader.class.getDeclaredMethod(&quot;addURL&quot;, URL.class); method.setAccessible(true); method.invoke(systemClassLoader, tools.toURI().toURL());<\/code><\/pre>\n<p>  \u041d\u0443 \u0432\u043e\u0442 \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u0432\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b.<\/p>\n<p>  \u0417\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0442\u0435\u043a\u0443\u0449\u0438\u043c OSGi-\u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440\u043e\u043c, \u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0432\u0441\u0435\u0433\u0434\u0430, \u0442.\u043a. \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f attach \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443, \u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437. OSGi \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440\u044b \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0431\u0430\u043d\u0434\u043b\u0430 \u2014 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437 \u043d\u043e\u0432\u044b\u0439. \u0422\u0430\u043a \u0447\u0442\u043e \u0440\u0438\u0441\u043a\u0443\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a\u0443\u044e \u0448\u0442\u0443\u043a\u0443:<\/p>\n<blockquote><p>\u2026 19 more<br \/>  Caused by: com.sun.tools.attach.AttachNotSupportedException: no providers installed<br \/>   at com.sun.tools.attach.VirtualMachine.attach(VirtualMachine.java:203)<\/p><\/blockquote>\n<p>  \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043d\u0435 \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435, \u043d\u043e \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u043f\u0440\u0438\u0447\u0438\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u2014 \u0443\u0437\u043d\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0434\u0435\u0431\u0430\u0436\u0438\u0432 attach \u043c\u0435\u0442\u043e\u0434 \u0438 \u0443\u0432\u0438\u0434\u0435\u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>  \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0441, \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0440\u0443\u0437\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446-\u0442\u043e \u043f\u0440\u0438\u0430\u0442\u0442\u0430\u0447\u0438\u0442\u044c \u043d\u0430\u0448 \u0430\u0433\u0435\u043d\u0442:<\/p>\n<pre><code class=\"java\">Method attach = virtualMachine.getMethod(&quot;attach&quot;, String.class);                 Method loadAgent = virtualMachine.getMethod(&quot;loadAgent&quot;, String.class);                 Method detach = virtualMachine.getMethod(&quot;detach&quot;);                 Object vm = null;                 try {                     final String pid = getPid();                     log.debug(&quot;Current VM PID={}&quot;, pid);                     log.trace(&quot;Attaching to VM with PID={}&quot;, pid);                     vm = attach.invoke(null, pid);                     final File agentFile = getAgentFile();                     log.debug(&quot;Agent file: {}&quot;, agentFile);                     loadAgent.invoke(vm, agentFile.getAbsolutePath());                 } finally {                     tryToDetach(vm, detach); }<\/code><\/pre>\n<p>  \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u044c\u044e \u0442\u0443\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f pid \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b:<\/p>\n<pre><code class=\"java\">    private String getPid() {         String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();         return nameOfRunningVM.split(&quot;@&quot;, 2)[0];     }<\/code><\/pre>\n<p>  \u0421\u043f\u043e\u0441\u043e\u0431 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439, \u043d\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0431\u043e\u0447\u0438\u0439, \u0430 \u0432 <a href=\"http:\/\/openjdk.java.net\/jeps\/102\">Java 9 Process API<\/a> \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u0431\u0435\u0437 \u043b\u0438\u0448\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<h4>Add-on<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0432\u0441\u0442\u0440\u043e\u0438\u043c \u044d\u0442\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 add-on. \u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0434\u0434\u043e\u043d\u0430 \u2014 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e \u0441\u043f\u0440\u0438\u043d\u0433\u043e\u0432\u043e\u0433\u043e InitializingBean. <\/p>\n<pre><code class=\"java\">    @Override     public void afterPropertiesSet() throws Exception {         this.agentInstaller.install();         this.serviceTracker.open();     }<\/code><\/pre>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0430\u0433\u0435\u043d\u0442\u0430(\u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043d\u0443\u044e \u0432\u044b\u0448\u0435), \u0430 \u0437\u0430\u0442\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c <a href=\"https:\/\/osgi.org\/javadoc\/r4v42\/org\/osgi\/util\/tracker\/ServiceTracker.html\">ServiceTracker<\/a> \u2014 \u043e\u0434\u0438\u043d \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <a href=\"https:\/\/www.osgi.org\/wp-content\/uploads\/whiteboard1.pdf\">whiteboard<\/a> \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u0432 OSGi. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u043e\u0442\u043a\u043e, \u0442\u043e \u044d\u0442\u0430 \u0448\u0442\u0443\u043a\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u043b\u0435\u043d\u0438\u0438\/\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0435.<\/p>\n<pre><code class=\"java\">private ServiceTracker&lt;InstrumentationConsumer, Void&gt; initTracker(final BundleContext bundleContext, final InstrumentationProvider instrumentationProvider) {         return new ServiceTracker&lt;&gt;(bundleContext, InstrumentationConsumer.class, new ServiceTrackerCustomizer&lt;InstrumentationConsumer, Void&gt;() {             @Override             public Void addingService(ServiceReference&lt;InstrumentationConsumer&gt; serviceReference) {\/\/\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u043a\u043e\u0434 \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0442\u0438\u043f\u0430 InstrumentationConsumer                 try {                     log.trace(&quot;addingService called&quot;);                     final InstrumentationConsumer consumer = bundleContext.getService(serviceReference);                     log.debug(&quot;Consumer: {}&quot;, consumer);                     if (consumer != null) {                         final Instrumentation instrumentation;                         try {                             instrumentation = instrumentationProvider.getInstrumentation();                             consumer.applyInstrumentation(instrumentation);                         } catch (InstrumentationAgentException e) {                             log.error(&quot;Error on getting insrumentation&quot;, e);                         }                     }                 } catch (Throwable t) {                     log.error(&quot;Error on 'addingService'&quot;, t);                 }                 return null;             }              @Override             public void modifiedService(ServiceReference&lt;InstrumentationConsumer&gt; serviceReference, Void aVoid) {              }              @Override             public void removedService(ServiceReference&lt;InstrumentationConsumer&gt; serviceReference, Void aVoid) {              } });<\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 InstrumentationConsumer, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434 applyInstrumentation \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c java.lang.instrument.Instrumentation, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u043d\u0430\u043c\u0438 \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"java\">@Component public class InstrumentationProviderImpl implements InstrumentationProvider {     private static final Logger log = LoggerFactory.getLogger(InstrumentationProviderImpl.class);     @Override     public Instrumentation getInstrumentation() throws InstrumentationAgentException {         try {             final Class&lt;?&gt; agentClass = ClassLoader.getSystemClassLoader().loadClass(INSTRUMENTATION_CLASS_NAME);\/\/\u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0430\u0433\u0435\u043d\u0442\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0433\u0440\u0443\u0437\u0438\u0442 javaagents             log.debug(&quot;Agent class loaded from system classloader&quot;, agentClass);             final Field instrumentation = agentClass.getDeclaredField(INSTRUMENTATION_FIELD_NAME);\/\/\u0434\u043e\u0441\u0442\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 reflection             log.debug(&quot;Instrumentation field: {}&quot;, instrumentation);             final Object instrumentationValue = instrumentation.get(null);             if (instrumentationValue == null) {                 throw new NullPointerException(&quot;instrumentation data is null. Seems agent is not installed&quot;);             }             return (Instrumentation) instrumentationValue;         } catch (Throwable e) {             String msg = &quot;Error getting instrumentation&quot;;             log.error(msg, e);             throw new InstrumentationAgentException(&quot;Error getting instrumentation&quot;, e);         }     } }<\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u0434\u0432\u0438\u0436\u043a\u0430 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438.<\/p>\n<h4>\u0414\u0432\u0438\u0436\u043e\u043a \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438<\/h4>\n<p>  \u041d\u0430\u0445\u043e\u0434\u0438\u043c \u0442\u043e\u0447\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0432\u043d\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u2014 \u043a\u043b\u0430\u0441\u0441 DefaultIssueService(\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f\/\u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0434\u0443\u0442 \u0447\u0435\u0440\u0435\u0437 \u044d\u0442\u0443 \u0442\u043e\u0447\u043a\u0443, \u043d\u043e \u044d\u0442\u043e \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f \u0442\u0435\u043c\u0430), \u0438 \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<p>  validateCreate:<\/p>\n<pre><code class=\"java\">IssueService.CreateValidationResult validateCreate(@Nullable ApplicationUser var1, IssueInputParameters var2);<\/code><\/pre>\n<p>  \u0438 validateUpdate:<\/p>\n<pre><code class=\"java\">IssueService.UpdateValidationResult validateUpdate(@Nullable ApplicationUser var1, Long var2, IssueInputParameters var3);<\/code><\/pre>\n<p>  \u0438 \u043f\u0440\u0438\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u043c \u043a\u0430\u043a\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442.<\/p>\n<p>  \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0431\u044b\u043b\u0430 \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043d\u0430\u0448\u0438\u043c \u043a\u043e\u0434\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442.<\/p>\n<p>  ByteBuddy \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442 \u043d\u0430\u043c 2 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0443\u043c\u043a\u0438: \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 Advice. \u0420\u0430\u0437\u043d\u0438\u0446\u0443 \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u0432 \u0445\u043e\u0440\u043e\u0448\u043e \u0432\u0438\u0434\u043d\u043e \u043d\u0430 \u0441\u043b\u0430\u0439\u0434\u0435 <a href=\"http:\/\/www.slideshare.net\/RafaelWinterhalter\/runtime-code-generation-for-the-jvm\">\u043f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a> \u0420\u0430\u0444\u0430\u044d\u043b\u044f.<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/1ea\/558\/ac8\/1ea558ac8ba64041b1fbfcadf5e6c68a.PNG\" \/><\/div>\n<p>  Interceptor API \u0445\u043e\u0440\u043e\u0448\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d, \u0432 \u0435\u0433\u043e \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 <a href=\"http:\/\/bytebuddy.net\/#\/tutorial\">\u0442\u0443\u0442<\/a>. \u0412 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0431\u0430\u0439\u0442\u043a\u043e\u0434 \u0432\u044b\u0437\u043e\u0432 Interceptor&#8217;\u0430 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0412\u041c\u0415\u0421\u0422\u041e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430. <\/p>\n<p>  \u041f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u043f\u043e\u0441\u043e\u0431 \u044f \u0432\u044b\u044f\u0432\u0438\u043b 2 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0430:<\/p>\n<ul>\n<li>\u0412 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0438 \u0434\u0430\u0436\u0435 <a href=\"http:\/\/bytebuddy.net\/#\/tutorial\">\u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430<\/a>. \u041e\u0434\u043d\u0430\u043a\u043e, \u0438\u0437-\u0437\u0430 <a href=\"http:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/Instrumentation.html\">\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432<\/a>, \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0443\u0436\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043c\u044b \u0442\u0435\u0440\u044f\u0435\u043c(\u0442.\u043a. \u043e\u043d \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d \u043a\u0430\u043a \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0442\u043e\u0433\u043e \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u0430). \u0422\u0430\u043a \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0435 \u0437\u0430\u043d\u043e\u0432\u043e \u0441\u0430\u043c\u0438\u043c \u0441\u0430\u043c\u0438\u043c.\n<\/li>\n<li>\u0422.\u043a. \u043c\u044b \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430, \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c \u043c\u0435\u0436\u0434\u0443 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440\u043e\u0432. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 \u0432\u043d\u0443\u0442\u0440\u0438 OSGi-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442. \u041d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438\u0437 API JIRA \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f WebappClassLoader&#8217;\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u043d\u0435 OSGi, \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u0430\u0448\u0435\u0433\u043e Interceptor&#8217;\u0430 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0437\u0430\u0441\u043b\u0443\u0436\u0435\u043d\u043d\u044b\u0439 ClassNotFoundException.<\/li>\n<\/ul>\n<p>  \u0412 \u0445\u043e\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0443 \u043c\u0435\u043d\u044f \u0440\u043e\u0434\u0438\u043b\u0441\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043d\u043e \u0442.\u043a. \u043e\u043d\u043e \u0432\u043c\u0435\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043b\u043e\u0433\u0438\u043a\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u044f \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0431\u0435\u0437 \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u043b\u043e\u0436\u0443 \u043f\u043e\u0434 \u0441\u043f\u043e\u0439\u043b\u0435\u0440\u043e\u043c.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0438\u0434\u0435\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0440\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u0439 WebappClassLoader&#8217;\u0430 \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0443\u0434\u0430 \u043d\u0435\u043a\u0438\u0439 \u043f\u0440\u043e\u043a\u0441\u0438 ClassLoader, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e BundleClassLoader, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044e WebappClassLoader&#8217;\u0430<\/p>\n<p>  \u0412\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/57c\/5b2\/b2b\/57c5b2b2b84e4997bf98c55ef4b4d3bc.png\" \/><\/div>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432\u044b\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"java\">private void tryToFixClassloader(ClassLoader originalClassLoader, BundleWiringImpl.BundleClassLoader bundleClassLoader) {         try {             final ClassLoader originalParent = originalClassLoader.getParent();             if (originalParent != null) {                 if (!(originalParent instanceof BundleProxyClassLoader)) {                     final BundleProxyClassLoader proxyClassLoader = new BundleProxyClassLoader&lt;&gt;(originalParent, bundleClassLoader);                     FieldUtils.writeDeclaredField(originalClassLoader, &quot;parent&quot;, proxyClassLoader, true);                 }             }         } catch (IllegalAccessException e) {             log.warn(&quot;Error on try to fix originalClassLoader {}&quot;, originalClassLoader, e);         } }<\/code><\/pre>\n<p>  \u041f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u0435\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0432 \u0431\u043b\u043e\u043a\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"java\">... .transform((builder, typeDescription, classloader) -&gt; { builder.method(named(&quot;validateCreate&quot;).and(ElementMatchers.isPublic())).intercept(MethodDelegation.to(Interceptor.class));                     if (!ClassUtils.isVisible(InstrumentationConsumer.class, classloader)) {                     tryToFixClassloader(classloader, (BundleWiringImpl.BundleClassLoader) Interceptor.class.getClassLoader());                 }              })             .installOn(instrumentation);<\/code><\/pre>\n<p>  \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c OSGi \u043a\u043b\u0430\u0441\u0441\u044b \u0447\u0435\u0440\u0435\u0437 WebappClassLoader. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u043e \u0447\u0435\u043c \u043d\u0430\u0434\u043e \u043f\u043e\u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u2014 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e OSGi \u043a\u043b\u0430\u0441\u0441\u044b, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u043d\u0435 OSGi, \u0442.\u043a. \u044d\u0442\u043e, \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u0437\u0430\u0446\u0438\u043a\u043b\u0438\u0432\u0430\u043d\u0438\u044e \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\u043c. <br \/>  \u041a\u043e\u0434 BundleProxyClassLoader:<\/p>\n<pre><code class=\"java\">class BundleProxyClassLoader&lt;T extends BundleWiringImpl.BundleClassLoader&gt; extends ClassLoader {          private static final Logger log = LoggerFactory.getLogger(BundleProxyClassLoader.class);          private final Set&lt;T&gt; proxies;         private final Method loadClass;         private final Method shouldDelegate;          public BundleProxyClassLoader(ClassLoader parent, T proxy) {             super(parent);             this.loadClass = getLoadClassMethod();             this.shouldDelegate = getShouldDelegateMethod();             this.proxies = new HashSet&lt;&gt;();             proxies.add(proxy);         }          private Method getLoadClassMethod() throws IllegalStateException {             try {                 Method loadClass = ClassLoader.class.getDeclaredMethod(&quot;loadClass&quot;, String.class, boolean.class);                 loadClass.setAccessible(true);                 return loadClass;             } catch (NoSuchMethodException e) {                 throw new IllegalStateException(&quot;Failed to get loadClass method&quot;, e);             }         }          private Method getShouldDelegateMethod() throws IllegalStateException {             try {                 Method shouldDelegate = BundleWiringImpl.class.getDeclaredMethod(&quot;shouldBootDelegate&quot;, String.class);                 shouldDelegate.setAccessible(true);                 return shouldDelegate;             } catch (NoSuchMethodException e) {                 throw new IllegalStateException(&quot;Failed to get shouldDelegate method&quot;, e);             }         }          @Override         public Class&lt;?&gt; loadClass(String name, boolean resolve) throws ClassNotFoundException {             synchronized (getClassLoadingLock(name)) {                 log.trace(&quot;Trying to find already loaded class {}&quot;, name);                 Class&lt;?&gt; c = findLoadedClass(name);                 if (c == null) {                     log.trace(&quot;This is new class. Trying to load {} with OSGi&quot;, name);                     c = tryToLoadWithProxies(name, resolve);                     if (c == null) {                         log.trace(&quot;Failed to load with OSGi. Trying to load {} with parent CL&quot;, name);                         c = super.loadClass(name, resolve);                     }                 }                 if (c == null) {                     throw new ClassNotFoundException(name);                 }                 return c;             }         }          private Class&lt;?&gt; tryToLoadWithProxies(String name, boolean resolve) {             for (T proxy : proxies) {                 try {                     final String pkgName = Util.getClassPackage(name);                     \/\/avoid cycle                     if(!isShouldDelegatePackageLoad(proxy, pkgName)) {                         log.trace(&quot;The load of class {} should not be delegated to OSGI parent, so let's try to load with bundles&quot;, name);                         return (Class&lt;?&gt;) this.loadClass.invoke(proxy, name, resolve);                     }                 } catch (ReflectiveOperationException e) {                     log.trace(&quot;Class {} is not found with {}&quot;, name, proxy);                 }             }             return null;         }          private boolean isShouldDelegatePackageLoad(T proxy, String pkgName) throws IllegalAccessException, InvocationTargetException {             return (boolean)this.shouldDelegate.invoke(                     FieldUtils.readDeclaredField(proxy, &quot;m_wiring&quot;, true),                     pkgName             );         }     }<\/code><\/pre>\n<p>  \u042f \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u043b \u0435\u0433\u043e \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043a\u0442\u043e-\u0442\u043e \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u044d\u0442\u0443 \u0438\u0434\u0435\u044e.  <\/div>\n<\/div>\n<p>  \u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u2014 \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Advice. \u042d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0445\u0443\u0436\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u2014 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u0438\u043a\u0435\u0442\u0430\u0445 \u043d\u0430 <a href=\"https:\/\/github.com\/raphw\/byte-buddy\/issues\/110\">Github<\/a> \u0438 \u043e\u0442\u0432\u0435\u0442\u0430\u0445 \u043d\u0430 <a href=\"http:\/\/stackoverflow.com\/questions\/35968530\/retransform-classes-with-byte-buddy\">StackOverflow<\/a>. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041d\u043e \u043d\u0435 \u0432\u0441\u0435 \u0442\u0430\u043a \u043f\u043b\u043e\u0445\u043e<\/b><\/p>\n<div class=\"spoiler_text\">\u0422\u0443\u0442 \u043d\u0430\u0434\u043e \u043e\u0442\u0434\u0430\u0442\u044c \u0420\u0430\u0444\u0430\u044d\u043b\u044e \u0434\u043e\u043b\u0436\u043d\u043e\u0435 \u2014 \u0432\u0441\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0438 \u0442\u0438\u043a\u0435\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0432\u0438\u0434\u0435\u043b \u0441\u043d\u0430\u0431\u0436\u0435\u043d\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439\u0448\u0438\u043c\u0438 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u0442\u0430\u043a \u0447\u0442\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043d\u0435 \u0442\u0440\u0443\u0434\u043d\u043e \u2014 \u043d\u0430\u0434\u0435\u044e\u0441\u044c \u044d\u0442\u0438 \u0442\u0440\u0443\u0434\u044b \u043f\u0440\u0438\u043d\u0435\u0441\u0443\u0442 \u043f\u043b\u043e\u0434\u044b \u0438 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c Byte Buddy \u0432 \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432.  <\/div>\n<\/div>\n<p>  \u041e\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043e\u043d \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0430\u0448\u0438 advice-\u043c\u0435\u0442\u043e\u0434\u044b <b>\u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u044e\u0442\u0441\u044f<\/b> \u0432 \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430. \u0414\u043b\u044f \u043d\u0430\u0441 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442: <\/p>\n<ul>\n<li>\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u043b\u044f\u0441\u043e\u043a \u0441 ClassLoader&#8217;\u0430\u043c\u0438<\/li>\n<li>\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u2014 \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043d\u0435\u043a\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0434\u043e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435<\/li>\n<\/ul>\n<p>  \u0417\u0432\u0443\u0447\u0438\u0442 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e, \u043d\u0430\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0448\u0438\u043a\u0430\u0440\u043d\u044b\u0439 API \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430(\u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f) \u0438 \u0434\u0430\u0436\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0440\u0430\u0431\u043e\u0442\u044b Advice&#8217;\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0434\u043e \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u041d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u00ab\u043d\u043e\u00bb, \u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d:<\/p>\n<ul>\n<li>\u0432\u0435\u0441\u044c \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0444\u043e\u0440\u043c\u043b\u0435\u043d \u043e\u0434\u043d\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c<\/li>\n<li>\u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u0441\u044f, \u0432 \u0442.\u0447. \u0438 \u0430\u043d\u043e\u043d\u0438\u043c\u043d\u044b\u0445(\u043f\u0440\u043e\u0449\u0430\u0439\u0442\u0435 \u043b\u044f\u043c\u0431\u0434\u044b!)<\/li>\n<li>\u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u043d\u0438\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u2014 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0443\u0436\u043d\u043e \u0431\u0440\u043e\u0441\u0430\u0442\u044c \u044f\u0432\u043d\u043e \u0432 \u0442\u0435\u043b\u0435 \u043c\u0435\u0442\u043e\u0434\u0430<\/li>\n<\/ul>\n<p>  <i>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u044d\u0442\u0438\u0445 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 Byte Buddy \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b<\/i><br \/>  \u041d\u0443 \u0447\u0442\u043e \u0436, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u0441\u0442\u0438\u043b\u0435 Advice. \u041a\u0430\u043a \u043c\u044b \u043f\u043e\u043c\u043d\u0438\u043c, \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u0442\u044c\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u2014 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0438 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u0438 \u043d\u043e\u0432\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043e\u043d\u0430 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u043b\u0430\u0441\u044c \u0432 \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 validateCreate\/validateUpdate, \u0430 \u0441\u0430\u043c \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430 DefaultIssueService \u043c\u0435\u043d\u044f\u0442\u044c \u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u043b\u043e\u0441\u044c.<br \/>  \u0412 OSGi \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043b\u0435\u0433\u043a\u043e, \u043d\u043e DefaultIssueService \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430 \u0440\u0430\u043c\u043a\u0430\u043c\u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c OSGi \u043f\u0440\u0438\u0435\u043c\u044b \u0442\u0443\u0442 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f.<\/p>\n<p>  \u041d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 API JIRA. \u041a\u0430\u0436\u0434\u044b\u0439 add-on \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 JIRA \u043a\u0430\u043a \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Plugin(\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u043d\u0430\u0434 Bundle \u0441 \u0440\u044f\u0434\u043e\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439) \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u044d\u0442\u043e\u0442 plugin \u0438\u0441\u043a\u0430\u0442\u044c. <\/p>\n<p>  \u041a\u043b\u044e\u0447 \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u043c\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0430\u0434\u0434\u043e\u043d\u0430, plugin API \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u043c \u0436\u0435 \u043a\u043b\u0430\u0441\u0441\u043b\u043e\u0430\u0434\u0435\u0440\u043e\u043c, \u0447\u0442\u043e \u0438 \u043d\u0430\u0448 DefaultIssueService \u2014 \u0442\u0430\u043a \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0432 \u043d\u0430\u0448\u0435\u043c advice&#8217;\u0435 \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430\u0448 plugin \u0438 \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0443\u0436\u0435 \u043b\u044e\u0431\u043e\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u0442\u0438\u043c plugin&#8217;\u043e\u043c \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043d\u0430\u0448 \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440 \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a.<\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u043f\u044f\u0442\u044c-\u0442\u0430\u043a\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 com.atlassian.jira.component.ComponentAccessor#getOSGiComponentInstanceOfType.<br \/>  \u0418 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043c\u0430\u0433\u0438\u0438:<\/p>\n<pre><code class=\"java\">public class DefaultIssueServiceValidateCreateAdvice {     @Advice.OnMethodExit(onThrowable = IllegalArgumentException.class)     public static void intercept(         @Advice.Return(readOnly = false) CreateValidationResult originalResult,\/\/\u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0438\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0432 \u044d\u0442\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e - \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0442\u0430\u0432\u0438\u043c (readOnly = false)         @Advice.Thrown Throwable throwable,\/\/\u0435\u0441\u043b\u0438 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u0438\u043d\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 - \u043c\u044b \u0435\u0433\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c         @Advice.Argument(0) ApplicationUser user,         @Advice.Argument(1) IssueInputParameters issueInputParameters     ) {         try {             if (throwable == null) {                 \/\/current plugin key                 final Plugin plugin = ComponentAccessor.getPluginAccessor().getEnabledPlugin(&quot;org.jrx.jira.instrumentation.issue-validation&quot;);                 \/\/related aggregator class                 final Class&lt;?&gt; issueValidatorClass = plugin != null ? plugin.getClassLoader().loadClass(&quot;org.jrx.jira.instrumentation.validation.spi.issueservice.IssueServiceValidateCreateValidatorAggregator&quot;) : null;                 final Object issueValidator = issueValidatorClass != null ? ComponentAccessor.getOSGiComponentInstanceOfType(issueValidatorClass) : null;\/\/\u0432\u043e\u0442 \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 API JIRA                 if (issueValidator != null) {                     final Method validate = issueValidator.getClass().getMethod(&quot;validate&quot;, CreateValidationResult.class, ApplicationUser.class, IssueInputParameters.class);                     if (validate != null) {                         final CreateValidationResult validationResult = (CreateValidationResult) validate                             .invoke(issueValidator, originalResult, user, issueInputParameters);                         if (validationResult != null) {                             originalResult = validationResult;                         }                     } else {                         System.err.println(&quot;==**Warn: method validate is not found on aggregator &quot; + &quot;**==&quot;);                     }                 }             }         \/\/Nothing should break service         } catch (Throwable e) {             System.err.println(&quot;==**Warn: Exception on additional logic of validateCreate &quot; + e + &quot;**==&quot;);         }     } }<\/code><\/pre>\n<p>  DefaultIssueServiceValidateUpdateAdvice \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0441 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c\u044e \u0434\u043e \u0438\u043c\u0435\u043d \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432. \u041f\u0440\u0438\u0448\u043b\u0430 \u043f\u043e\u0440\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c InstrumentationConsumer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0448 advice \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u043c\u0435\u0442\u043e\u0434\u0443.<\/p>\n<pre><code class=\"java\">@Component @ExportAsService public class DefaultIssueServiceTransformer implements InstrumentationConsumer {      private static final Logger log = LoggerFactory.getLogger(DefaultIssueServiceTransformer.class);     private static final AgentBuilder.Listener listener = new LogTransformListener(log);     private final String DEFAULT_ISSUE_SERVICE_CLASS_NAME = &quot;com.atlassian.jira.bc.issue.DefaultIssueService&quot;;      @Override     public void applyInstrumentation(Instrumentation instrumentation) {         new AgentBuilder.Default().disableClassFormatChanges()             .with(new AgentBuilder.Listener.Filtering(                 new StringMatcher(DEFAULT_ISSUE_SERVICE_CLASS_NAME, EQUALS_FULLY),                 listener             ))             .with(AgentBuilder.TypeStrategy.Default.REDEFINE)             .with(AgentBuilder.RedefinitionStrategy.REDEFINITION)             .with(AgentBuilder.InitializationStrategy.NoOp.INSTANCE)             .type(named(DEFAULT_ISSUE_SERVICE_CLASS_NAME))             .transform((builder, typeDescription, classloader) -&gt;                     builder                 \/\/transformation is idempotent!!! You can call it many times with same effect                 \/\/no way to add advice on advice if it applies to original class                 \/\/https:\/\/github.com\/raphw\/byte-buddy\/issues\/206                 .visit(Advice.to(DefaultIssueServiceValidateCreateAdvice.class).on(named(&quot;validateCreate&quot;).and(ElementMatchers.isPublic())))                 .visit(Advice.to(DefaultIssueServiceValidateUpdateAdvice.class).on(named(&quot;validateUpdate&quot;).and(ElementMatchers.isPublic()))))             .installOn(instrumentation);     } }<\/code><\/pre>\n<p>  \u0422\u0443\u0442 \u043d\u0430\u0434\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e\u0431 \u043e\u0434\u043d\u043e\u043c \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u043c \u0431\u043e\u043d\u0443\u0441\u0435. \u041f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 advice&#8217;\u0430 \u2014 \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u043e! \u041d\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0431\u043e\u0442\u0438\u0442\u044c\u0441\u044f \u043e \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0434\u0432\u0430\u0436\u0434\u044b \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0430\u0434\u0434\u043e\u043d\u0430 \u2014 <a href=\"https:\/\/github.com\/raphw\/byte-buddy\/issues\/206\">\u0437\u0430 \u043d\u0430\u0441 \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0435\u0442 VM<\/a>.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\u041a\u0430\u043a \u044f \u0443\u0436\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u043b, \u0438\u0437-\u0437\u0430 <a href=\"http:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/Instrumentation.html\">\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/a> \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043c\u0435\u0442\u0430\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 \u043d\u0435\u043b\u044c\u0437\u044f, \u043d\u043e \u0441 \u043f\u043e\u0434\u0430\u0447\u0438 \u0420\u0430\u0444\u0430\u044d\u043b\u044f \u044f \u043f\u0440\u043e\u0432\u0435\u043b \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442 \u043f\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u043a \u043a\u043b\u0430\u0441\u0441\u0443 \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0439. \u0415\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438, \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 JRE (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, JAXB \u0438 \u0442.\u0434.), \u0442\u043e \u0441 \u0438\u0445 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u2014 \u0432\u0435\u0440\u0441\u0438\u044e, \u0434\u0430\u0442\u0443 \u0438 \u0442.\u0434.<br \/>  \u0412 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u043f\u0430\u043b\u043e, \u0442.\u043a. \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.  <\/div>\n<\/div>\n<p>  \u041d\u0443 \u0447\u0442\u043e \u0436, \u0434\u0435\u043b\u043e \u0437\u0430 \u043c\u0430\u043b\u044b\u043c \u2014 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0430\u0433\u0440\u0435\u0433\u0430\u0442\u043e\u0440. \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c API \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"java\">public interface IssueServiceValidateCreateValidator {     @Nonnull CreateValidationResult validate(         final @Nonnull CreateValidationResult originalResult,         final ApplicationUser user,         final IssueInputParameters issueInputParameters     ); }<\/code><\/pre>\n<p>  \u0414\u0430\u043b\u044c\u0448\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 OSGi \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0438\u0445:<\/p>\n<pre><code class=\"java\">@Component @ExportAsService(IssueServiceValidateCreateValidatorAggregator.class) \/\/\u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043e\u0444\u043e\u0440\u043c\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u0430\u043a OSGi-\u0441\u0435\u0440\u0432\u0438\u0441 public class IssueServiceValidateCreateValidatorAggregator implements IssueServiceValidateCreateValidator {     private static final Logger log = LoggerFactory.getLogger(IssueServiceValidateCreateValidatorAggregator.class);     private final BundleContext bundleContext;      @Autowired     public IssueServiceValidateCreateValidatorAggregator(BundleContext bundleContext) {         this.bundleContext = bundleContext;     }      @Nonnull     @Override     public IssueService.CreateValidationResult validate(@Nonnull final IssueService.CreateValidationResult originalResult, final ApplicationUser user, final IssueInputParameters issueInputParameters) {         try {             log.trace(&quot;Executing validate of IssueServiceValidateCreateValidatorAggregator&quot;);             final Collection&lt;ServiceReference&lt;IssueServiceValidateCreateValidator&gt;&gt; serviceReferences = bundleContext.getServiceReferences(IssueServiceValidateCreateValidator.class, null);\/\/\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 IssueServiceValidateCreateValidator - \u0442\u0443\u0442 \u0443\u0436\u0435 \u043e\u0431\u044b\u0447\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 OSGi             log.debug(&quot;Found services: {}&quot;, serviceReferences);             IssueService.CreateValidationResult result = originalResult;             for (ServiceReference&lt;IssueServiceValidateCreateValidator&gt; serviceReference : serviceReferences) {                 final IssueServiceValidateCreateValidator service = bundleContext.getService(serviceReference);                 if (service != null) {                     result = service.validate(result, user, issueInputParameters);\/\/\u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0432\u0441\u0435\u043c \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435                 } else {                     log.debug(&quot;Failed to get service from {}&quot;, serviceReference);                 }             }             return result;         } catch (InvalidSyntaxException e) {             log.warn(&quot;Exception on getting IssueServiceValidateCreateValidator&quot;, e);             return originalResult;         }     } }<\/code><\/pre>\n<p>  \u0412\u0441\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u2014 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c, \u0443\u0441\u0442\u0430\u0432\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c<\/p>\n<h4>\u0422\u0435\u0441\u0442\u043e\u0432\u0430\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f<\/h4>\n<p>  \u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443:<\/p>\n<pre><code class=\"java\">@Component @ExportAsService public class TestIssueServiceCreateValidator implements IssueServiceValidateCreateValidator {     @Nonnull     @Override     public IssueService.CreateValidationResult validate(@Nonnull IssueService.CreateValidationResult originalResult, ApplicationUser user, IssueInputParameters issueInputParameters) {         originalResult.getErrorCollection().addError(IssueFieldConstants.ASSIGNEE, &quot;This validation works&quot;, ErrorCollection.Reason.VALIDATION_FAILED);         return originalResult;     } }<\/code><\/pre>\n<p>  \u041f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u0432\u0443\u0430\u043b\u044f!<\/p>\n<div style=\"text-align:center;\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/e45\/390\/934\/e45390934d8d4124a0e2cab8c49260f5.PNG\" \/><\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0438 \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e \u043b\u044e\u0431\u043e\u0439 \u0430\u0434\u0434\u043e\u043d \u0438\u0437 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0445 \u2014 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 JIRA \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<h3><font color=\"#9cc2ce\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/font><\/h3>\n<p>  \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f API \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 JIRA. \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u0432 production \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435 \u043e\u043a\u043e\u043d\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043a\u043e\u0441\u0442\u044b\u043b\u0435\u043d\u043e, \u0438 \u043f\u0440\u0438 \u0434\u043e\u043b\u0436\u043d\u043e\u0439 \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u00ab\u0431\u0435\u0437\u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447\u00bb \u2014 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0433\u043e\u0436\u0438\u0432\u0443\u0449\u0438\u0445 thirdparty \u0434\u0435\u0444\u0435\u043a\u0442\u043e\u0432, \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f API \u0438 \u0442.\u0434.<\/p>\n<p>  \u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441\u0430\u043c\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 <a href=\"https:\/\/github.com\/dzharikhin\/jira-instrumentation\">Github<\/a> \u2014 \u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435\u0441\u044c \u043d\u0430 \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u0435!<\/p>\n<p>  <b>\u0437.\u044b.<\/b> \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u044f \u043d\u0435 \u0441\u0442\u0430\u043b \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 add-on&#8217;\u043e\u0432 \u0434\u043b\u044f JIRA \u2014 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u044d\u0442\u0438\u043c \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/developer.atlassian.com\/docs\/getting-started\">\u0437\u0434\u0435\u0441\u044c<\/a>.<br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habrahabr.ru\/post\/316124\/\"> https:\/\/habrahabr.ru\/post\/316124\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0427\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 API \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043a\u043e\u0434 \u043d\u0435\u0442?<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/2fa\/67d\/0e1\/2fa67d0e1abc455385d45f4e5db19e64.jpg\"\/><\/p>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u043d\u0430\u0434\u0435\u0436\u0434\u043e\u0439 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 \u043f\u0430\u043a\u0435\u0442\u0430 <a href=\"https:\/\/docs.oracle.com\/javase\/8\/docs\/api\/java\/lang\/instrument\/package-summary.html\">java.lang.instrument<\/a>. \u0412\u0441\u0435\u043c, \u043a\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0447\u0442\u043e \u0438 \u043a\u0430\u043a \u0432 Java \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441 \u043a\u043e\u0434\u043e\u043c \u0432 \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0439 VM, \u0434\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434 \u043a\u0430\u0442.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-281546","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/281546","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=281546"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/281546\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=281546"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=281546"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=281546"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}