{"id":43745,"date":"2015-09-18T21:54:19","date_gmt":"2015-09-18T18:54:19","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=43745"},"modified":"2023-12-06T14:28:35","modified_gmt":"2023-12-06T12:28:35","slug":"java-agents","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html","title":{"rendered":"Java Agents"},"content":{"rendered":"<p><em>This article is part of our Academy Course titled <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/advanced-java.html\">Advanced Java<\/a>.<\/p>\n<p>This course is designed to help you make the most effective use of Java. It discusses advanced topics, including object creation, concurrency, serialization, reflection and many more. It will guide you through your journey to Java mastery! Check it out <a href=\"http:\/\/www.javacodegeeks.com\/2015\/09\/advanced-java.html\">here<\/a>!<\/em><\/p>\n<div class=\"toc\">\n<h4>Table Of Contents<\/h4>\n<dl>\n<dt><a href=\"#introduction\">1. Introduction<\/a><\/dt>\n<dt><a href=\"#two\">2. Java Agent Basics<\/a><\/dt>\n<dt><a href=\"#three\">3. Java Agent and Instrumentation<\/a><\/dt>\n<dt><a href=\"#four\">4. Writing Your First Java Agent<\/a><\/dt>\n<dt><a href=\"#five\">5. Running Java Agents<\/a><\/dt>\n<dt><a href=\"#six\">6. What\u2019s next<\/a><\/dt>\n<dt><a href=\"#seven\">7. Download the source code<\/a><\/dt>\n<\/dl>\n<\/div>\n<h2><a name=\"introduction\"><\/a>1. Introduction<\/h2>\n<p>In this last part of the tutorial we are going to talk about Java agents, a real black magic for regular Java developers out there. Java agents are able to &#8220;intrude&#8221; into the execution of Java applications running on the JVM at runtime by performing the direct modifications of the bytecode. Java agents are extremely as powerful as dangerous: they can do mostly everything however if something goes wrong, they can easily crash the JVM.<\/p>\n<p>The goal of this part is to demystify Java agents by explaining how they work, how to run them and showing off some simple examples where Java agents come as a clear advantage.<\/p>\n<h2><a name=\"two\"><\/a>2. Java Agent Basics<\/h2>\n<p>In its essence, a Java agent is a regular Java class which follows a set of strict conventions. The agent class must implement a <code>public static void premain(String agentArgs, Instrumentation inst)<\/code> method which becomes an agent entry point (similar to the <code>main<\/code> method for regular Java applications). <\/p>\n<p>Once the Java Virtual Machine (JVM) has initialized, each such <code>premain(String agentArgs, Instrumentation inst)<\/code> method of every agent will be called in the order the agents were specified on JVM start. When this initialization step is done, the real Java application <code>main<\/code> method will be called. <\/p>\n<p>However, if the class does not implement <code>public static void premain(String agentArgs, Instrumentation inst)<\/code> method, the JVM will try to look up and invoke another, overloaded version, <code>public static void premain(String agentArgs)<\/code>. Please notice that each <code>premain<\/code> method must return in order for the startup phase to proceed. <\/p>\n<p>Last but not least, the Java agent class may also have a <code>public static void agentmain(String agentArgs, Instrumentation inst)<\/code> or <code>public static void agentmain(String agentArgs)<\/code> methods which are used when the agent is started after JVM startup.<\/p>\n<p>It looks simple on the first glance but there is one more thing which Java agent implementation should provide as part of its packaging: manifest. Manifest files, usually located in the <strong>META-INF<\/strong> folder and named <strong>MANIFEST.MF<\/strong>, contain a various metadata related to package distribution.<\/p>\n<p>We have not talked about manifests along this tutorial because most of the time they are not required, however this is not the case with Java agents. The following attributes are defined for Java agents who are packaged as a Java archive (or simply JAR) files:<\/p>\n<table style=\"width:100%\">\n<tr>\n<td><strong>Manifest Attribute<\/strong><\/td>\n<td><strong>Description<\/strong><\/td>\n<\/tr>\n<tr>\n<td><strong>Premain-Class<\/strong><\/td>\n<td>\nWhen an agent is specified at JVM launch time this attribute defines the Java agent class:  the class containing the <code>premain<\/code> method. When an agent is specified at JVM launch time this attribute is required. If the attribute is not present the JVM will abort. <\/td>\n<\/tr>\n<tr>\n<td><strong>Agent-Class<\/strong><\/td>\n<td>If an implementation supports a mechanism to start Java agents sometime after the JVM has started then this attribute specifies the agent class: the class containing the <code>agentmain<\/code> method. This attribute is required and the agent will not be started if this attribute is not present. <\/td>\n<\/tr>\n<tr>\n<td><strong>Boot-Class-Path<\/strong><\/td>\n<td>A list of paths to be searched by the bootstrap class loader. Paths represent directories or libraries. <\/td>\n<\/tr>\n<tr>\n<td><strong>Can-Redefine-Classes<\/strong><\/td>\n<td>A value of <code>true<\/code> or <code>false<\/code>, case-insensitive and defines if the ability to redefine classes needed by this agent. This attribute is optional, the default is <code>false<\/code>. <\/td>\n<\/tr>\n<tr>\n<td><strong>Can-Retransform-Classes<\/strong><\/td>\n<td>A value of <code>true<\/code> or <code>false<\/code>, case-insensitive and defines if the ability to retransform classes needed by this agent. This attribute is optional, the default is <code>false<\/code>.<\/td>\n<\/tr>\n<tr>\n<td>\n<strong>Can-Set-Native-Method-Prefix<\/strong><\/td>\n<td>A value of <code>true<\/code> or <code>false<\/code>, case-insensitive and defines if the ability to set native method prefix needed by this agent. This attribute is optional, the default is <code>false<\/code>.<\/td>\n<\/tr>\n<\/table>\n<p>For more details please do not hesitate to consult <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/lang\/instrument\/package-summary.html\" target=\"_blank\" rel=\"noopener\">the official documentation<\/a> dedicated to Java agents and instrumentation.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h2><a name=\"three\"><\/a>3. Java Agent and Instrumentation<\/h2>\n<p>The instrumentation capabilities of Java agents are truly unlimited. Most noticeable ones include but are not limited to: <\/p>\n<ul>\n<li>Ability to redefine classes at run-time. The redefinition may change method bodies, the constant pool and attributes. The redefinition must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.  <\/li>\n<li>\nAbility to retransform classes at run-time. The retransformation may change method bodies, the constant pool and attributes. The retransformation must not add, remove or rename fields or methods, change the signatures of methods, or change inheritance.<\/li>\n<li>\nAbility to modify the failure handling of native method resolution by allowing retry with a prefix applied to the name.<\/li>\n<\/ul>\n<p>Please notice that retransformed or redefined class bytecode is not checked, verified and installed just after the transformations or redefinitions have been applied. If the resulting bytecode is erroneous or not correct, the exception will be thrown and that may crash JVM completely.<\/p>\n<h2><a name=\"four\"><\/a>4. Writing Your First Java Agent<\/h2>\n<p>In this section we are going to write a simple Java agent by implementing our own class transformer. With that being said, the only disadvantage working with Java agents is that in order to accomplish any more or less useful transformation, direct bytecode manipulation skills are required. And, unfortunately, theJava standard library does not provide any API (at least, documented ones) to make those bytecode manipulations possible.<\/p>\n<p>To fill this gap, creative Java community came up with a several excellent and at this moment very mature libraries, such as <a href=\"http:\/\/jboss-javassist.github.io\/javassist\/\" target=\"_blank\" rel=\"noopener\">Javassist<\/a> and <a href=\"http:\/\/asm.ow2.org\/\" target=\"_blank\" rel=\"noopener\">ASM<\/a>, just to name a few. Of those two, Javassist is much simpler to use and that is why it became the one we are going to employ as a bytecode manipulation solution. So far this is a first time we were not able to find the appropriate API in Java standard library and had no choice other than to use the one provided by the community.<\/p>\n<p>The example we are going to work on is rather simple but it is taken from real-world use case. Let us say we would like to capture URL of every HTTP connection opened by the Java applications. There are many ways to do that by directly modifying the Java source code but let us assume that the source code is not available due to license policies or whatnot. The typical example of the class which opens the HTTP connection may look like that:<\/p>\n<pre class=\"brush:java\">public class SampleClass {\n    public static void main( String[] args ) throws IOException {\n        fetch(\"http:\/\/www.google.com\");\n        fetch(\"http:\/\/www.yahoo.com\");\n    }\n\n    private static void fetch(final String address) \n            throws MalformedURLException, IOException {\n\n        final URL url = new URL(address);                \n        final URLConnection connection = url.openConnection();\n        \n        try( final BufferedReader in = new BufferedReader(\n                new InputStreamReader( connection.getInputStream() ) ) ) {\n            \n            String inputLine = null;\n            final StringBuffer sb = new StringBuffer();\n            while ( ( inputLine = in.readLine() ) != null) {\n                sb.append(inputLine);\n            }       \n            \n            System.out.println(\"Content size: \" + sb.length());\n        }\n    }\n}\n<\/pre>\n<p>Java agents fit very well into solving such kind of challenges.  We just need to define the transformer which will slightly modify <code>sun.net.www.protocol.http.HttpURLConnection<\/code> constructors by injecting the code to produce output to the console. Sounds scary but with <code>ClassFileTransformer<\/code> and <a href=\"http:\/\/jboss-javassist.github.io\/javassist\/\" target=\"_blank\" rel=\"noopener\">Javassist<\/a> it is very simple. Let us take a look on such transformer implementation:<\/p>\n<pre class=\"brush:java\">\npublic class SimpleClassTransformer implements ClassFileTransformer {\n  @Override\n  public byte[] transform( \n      final ClassLoader loader, \n      final String className,\n      final Class&lt;?&gt; classBeingRedefined, \n      final ProtectionDomain protectionDomain,\n      final byte[] classfileBuffer ) throws IllegalClassFormatException {\n        \n    if (className.endsWith(\"sun\/net\/www\/protocol\/http\/HttpURLConnection\")) {\n      try {\n        final ClassPool classPool = ClassPool.getDefault();\n        final CtClass clazz = \n          classPool.get(\"sun.net.www.protocol.http.HttpURLConnection\");\n                \n        for (final CtConstructor constructor: clazz.getConstructors()) {\n          constructor.insertAfter(\"System.out.println(this.getURL());\");\n        }\n    \n        byte[] byteCode = clazz.toBytecode();\n        clazz.detach();\n              \n        return byteCode;\n      } catch (final NotFoundException | CannotCompileException | IOException ex) {\n        ex.printStackTrace();\n      }\n    }\n        \n    return null;\n  }\n}\n<\/pre>\n<p>The <code>ClassPool<\/code> and all <code>CtXxx<\/code> classes (<code>CtClass<\/code>, <code>CtConstructor<\/code>) came from Javassist library. The transformation we have done is quite na\u00efve but it is here for demonstrational purposes. Firstly, because we were interested in HTTP communications only, the <code>sun.net.www.protocol.http.HttpURLConnection<\/code> is the class from standard Java library being responsible for that.<\/p>\n<p>Please notice that instead of \u2018.\u2019 separator, the <code>className<\/code> has the \u2018\/\u2019 one. Secondly, we looked for <code>HttpURLConnection<\/code> class and modified all its constructors by injecting the <code>System.out.println(this.getURL());<\/code> statement at the end. And lastly, we returned the new bytecode of the transformed version of the class so it is going to be used by JVM instead of original one.<\/p>\n<p>With that, the role of Java agent <code>premain<\/code> method would be just to add the instance of <code>SimpleClassTransformer<\/code> class to the instrumentation context:<\/p>\n<pre class=\"brush:java\">public class SimpleAgent {\n    public static void premain(String agentArgs, Instrumentation inst) {\n        final SimpleClassTransformer transformer = new SimpleClassTransformer();\n        inst.addTransformer(transformer);\n    }\n}\n<\/pre>\n<p>That\u2019s it. It looks quite easy and somewhat frightening at the same time. To finish up with Java agent, we have to supply the proper <strong>MANIFEST.MF<\/strong> so the JVM will be able to pick the right class. Here is the respective minimum set of the required attributes (please refer to <a href=\"#two\">Java Agent Basics<\/a> section for more details):<\/p>\n<pre class=\"brush:bash\">Manifest-Version: 1.0\nPremain-Class: com.javacodegeeks.advanced.agent.SimpleAgent\n<\/pre>\n<p>With that, out first Java agents is ready for a real battle. In the next section of the tutorial we are going to cover one of the ways to run Java agent along with your Java applications.<br \/>\n[ulp id=&#8217;w6F4W4SAMiyTapBF&#8217;]<br \/>\n&nbsp;<\/p>\n<h2><a name=\"five\"><\/a>5. Running Java Agents<\/h2>\n<p>When running from the command line, the Java agent could be passed to JVM instance using <code>-javaagent<\/code> argument which has following semantic:<\/p>\n<pre class=\"brush:bash\">\n-javaagent:&lt;path-to-jar&gt;[=options]\n<\/pre>\n<p>Where <code>&lt;path-to-jar&gt;<\/code> is the path to locate Java agent JAR archive, and options holds additional options which could be passed to the Java agent, more precisely through <code>agentArgs<\/code> argument. For example, the command line for running our Java agent from the section <a href=\"#four\">Writing Your First Java Agent<\/a> (using Java 7 version of it) will look like that (assuming that the agent JAR file is located in the current folder):<\/p>\n<pre class=\"brush:bash\">java -javaagent:advanced-java-part-15-java7.agents-0.0.1-SNAPSHOT.jar\n<\/pre>\n<p>When running the <code>SampleClass<\/code> class along with the <code>advanced-java-part-15-java7.agents-0.0.1-SNAPSHOT.jar<\/code> Java agent, the application is going to print on the console all the URLs (<a href=\"http:\/\/www.google.com\" target=\"_blank\" rel=\"noopener\">Google<\/a> and <a href=\"http:\/\/www.yahoo.com\" target=\"_blank\" rel=\"noopener\">Yahoo!<\/a> ) which were attempted to be accessed using HTTP protocol (followed by the content size of the <a href=\"http:\/\/www.google.com\" target=\"_blank\" rel=\"noopener\">Google<\/a> and <a href=\"http:\/\/www.yahoo.com\" target=\"_blank\" rel=\"noopener\">Yahoo!<\/a> search home web pages respectively):<\/p>\n<pre class=\"brush:bash\">http:\/\/www.google.com\nContent size: 20349\nhttp:\/\/www.yahoo.com\nContent size: 1387\n<\/pre>\n<p>Running the same <code>SampleClass<\/code> class without Java agent specified is going to output on the console only content size, no URLs (please notice the content size may vary):<\/p>\n<pre class=\"brush:bash\">Content size: 20349\nContent size: 1387\n<\/pre>\n<p>JVM makes it simple to run Java agents. However, please be warned, any mistakes or inaccurate bytecode generation may crash JVM, possibly losing important data your applications may hold at this moment.<\/p>\n<h2><a name=\"six\"><\/a>6. What\u2019s next<\/h2>\n<p>With this part coming to the end, the advanced Java tutorial is over as well. Hopefully you found it to be useful, practical and entertaining. There are many topics which have not been covered in it but you are very welcome to continue this deep dive into the wonderful world of Java language, platform, ecosystem and incredible community. Good luck!<\/p>\n<h2><a name=\"seven\"><\/a>7. Download the source code<\/h2>\n<p>You can download the source code of this lesson here: <a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/09\/advanced-java-part-15.zip\"><strong>advanced-java-part-15<\/strong><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses advanced topics, including object creation, concurrency, serialization, reflection and many more. It will guide you through your journey to Java mastery! Check it out here! Table Of Contents &hellip;<\/p>\n","protected":false},"author":141,"featured_media":148,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[343,88,580,557,65],"class_list":["post-43745","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-java","tag-annotations","tag-concurrency","tag-generics","tag-reflection","tag-serialization"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Java Agents - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Java Agents - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-09-18T18:54:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-06T12:28:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Java Agents\",\"datePublished\":\"2015-09-18T18:54:19+00:00\",\"dateModified\":\"2023-12-06T12:28:35+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html\"},\"wordCount\":1583,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"keywords\":[\"Annotations\",\"Concurrency\",\"Generics\",\"Reflection\",\"Serialization\"],\"articleSection\":[\"Core Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html\",\"name\":\"Java Agents - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"datePublished\":\"2015-09-18T18:54:19+00:00\",\"dateModified\":\"2023-12-06T12:28:35+00:00\",\"description\":\"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/java-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2015\\\/09\\\/java-agents.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Core Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/core-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Java Agents\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Java Agents - Java Code Geeks","description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html","og_locale":"en_US","og_type":"article","og_title":"Java Agents - Java Code Geeks","og_description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","og_url":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-09-18T18:54:19+00:00","article_modified_time":"2023-12-06T12:28:35+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","type":"image\/jpeg"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Java Agents","datePublished":"2015-09-18T18:54:19+00:00","dateModified":"2023-12-06T12:28:35+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html"},"wordCount":1583,"commentCount":4,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","keywords":["Annotations","Concurrency","Generics","Reflection","Serialization"],"articleSection":["Core Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html","url":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html","name":"Java Agents - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","datePublished":"2015-09-18T18:54:19+00:00","dateModified":"2023-12-06T12:28:35+00:00","description":"This article is part of our Academy Course titled Advanced Java. This course is designed to help you make the most effective use of Java. It discusses","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/java-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2015\/09\/java-agents.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Core Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/core-java"},{"@type":"ListItem","position":4,"name":"Java Agents"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43745","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=43745"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/43745\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/148"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=43745"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=43745"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=43745"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}