如何做网站对比网站开发与维护项目招标
web/
2025/9/30 6:52:40/
文章来源:
如何做网站对比,网站开发与维护项目招标,网站的建设费计入什么费用,广东企业网站制作java代理模式本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题#xff0c;包括对象创建#xff0c;并发#xff0c;序列化#xff0c;反射等。 它将指导您完成Java掌握的旅程#xff01; 在这里查看 #xff01;… java代理模式 本文是我们名为“ 高级Java ”的学院课程的一部分。 本课程旨在帮助您最有效地使用Java。 它讨论了高级主题包括对象创建并发序列化反射等。 它将指导您完成Java掌握的旅程 在这里查看 目录 1.简介 2. Java代理基础 3. Java代理和规范 4.编写您的第一个Java代理 5.运行Java代理 6.接下来 7.下载源代码 1.简介 在本教程的最后一部分中我们将讨论Java代理这对于在那里的常规Java开发人员是一个真正的魔咒。 通过执行字节码的直接修改Java代理能够“侵入”运行时在JVM上运行的Java应用程序的执行。 Java代理的功能和危险一样强大它们几乎可以执行所有操作但是如果出现问题它们很容易使JVM崩溃。 这部分的目的是通过解释Java代理如何工作如何运行它们以及展示一些简单的示例来揭开Java代理的神秘面纱Java代理显然具有优势。 2. Java代理基础 本质上Java代理是遵循一组严格约定的常规Java类。 代理类必须实现一个public static void premain(String agentArgs, Instrumentation inst)方法该方法成为代理的入口点类似于常规Java应用程序的main方法。 初始化Java虚拟机JVM后将按照在JVM启动时指定代理的顺序调用每个代理的每个此类premain(String agentArgs, Instrumentation inst)方法。 完成此初始化步骤后将调用真实的Java应用程序main方法。 但是如果该类未实现public static void premain(String agentArgs, Instrumentation inst)方法则JVM将尝试查找并调用另一个重载版本的public static void premain(String agentArgs) 。 请注意每个premain方法必须返回才能启动阶段。 最后但并非最不重要的一点是Java代理类还可以具有在JVM启动后启动代理时使用的public static void agentmain(String agentArgs, Instrumentation inst)或public static void agentmain(String agentArgs)方法。 乍看之下看起来很简单但Java代理实现还应提供其他一些内容作为其包装的一部分清单。 清单文件通常位于META-INF文件夹中名为MANIFEST.MF 包含与包分发有关的各种元数据。 我们在本教程中并未讨论清单因为大多数时候它们都不是必需的但是Java代理不是这种情况。 为打包为Java归档或简称JAR文件的Java代理定义了以下属性 清单属性 描述 初级班 在JVM启动时指定了代理时此属性定义Java代理类包含premain方法的类。 在JVM启动时指定代理时此属性是必需的。 如果该属性不存在JVM将中止。 代理级 如果实现支持在JVM启动后的某个时间启动Java代理的机制则此属性指定代理类包含agentmain方法的类。 此属性是必需的如果不存在该代理则不会启动代理。 引导类路径 引导类加载器要搜索的路径列表。 路径代表目录或库。 可以重新定义类 true或false值不区分大小写并且定义是否具有重新定义此代理所需的类的能力。 此属性是可选的默认值为false 。 可以重新转换类 true或false值不区分大小写并且定义是否具有重新转换此代理所需的类的能力。 此属性是可选的默认值为false 。 可以设置本机方法前缀 true或false值不区分大小写并且定义是否可以设置此代理所需的本机方法前缀。 此属性是可选的默认值为false 。 有关更多详细信息请随时查阅专用于Java代理和工具的官方文档 。 3. Java代理和规范 Java代理的检测功能确实是无限的。 最引人注意的包括但不限于 能够在运行时重新定义类。 重新定义可能会更改方法主体常量池和属性。 重新定义不得添加删除或重命名字段或方法更改方法的签名或更改继承。 能够在运行时重新转换类。 重新转换可能会更改方法主体常量池和属性。 重新转换不得添加删除或重命名字段或方法更改方法的签名或更改继承。 通过允许重命名使用前缀来修改本机方法解析的失败处理的能力。 请注意在应用转换或重新定义后不会检查验证和安装重新转换或重新定义的类字节码。 如果生成的字节码错误或不正确则将引发异常这可能会使JVM完全崩溃。 4.编写您的第一个Java代理 在本节中我们将通过实现我们自己的类转换器来编写一个简单的Java代理。 话虽如此使用Java代理的唯一缺点是为了完成或多或少的有用转换需要直接字节码操作技能。 而且不幸的是Java标准库没有提供任何API至少是有文档的API来使这些字节码操作成为可能。 为了填补这一空白富有创造力的Java社区提出了一些优秀的非常成熟的库例如Javassist和ASM 仅举几例。 在这两种方法中Javassist使用起来更简单这就是为什么它成为我们将要用作字节码操作解决方案的原因。 到目前为止这是我们第一次无法在Java标准库中找到合适的API除了使用社区提供的API之外别无选择。 我们将要处理的示例相当简单但它取自于实际的用例。 假设我们要捕获Java应用程序打开的每个HTTP连接的URL。 有很多方法可以通过直接修改Java源代码来做到这一点但让我们假设由于许可证策略或其他原因导致源代码不可用。 打开HTTP连接的类的典型示例如下所示 public class SampleClass {public static void main( String[] args ) throws IOException {fetch(http://www.google.com);fetch(http://www.yahoo.com);}private static void fetch(final String address) throws MalformedURLException, IOException {final URL url new URL(address); final URLConnection connection url.openConnection();try( final BufferedReader in new BufferedReader(new InputStreamReader( connection.getInputStream() ) ) ) {String inputLine null;final StringBuffer sb new StringBuffer();while ( ( inputLine in.readLine() ) ! null) {sb.append(inputLine);} System.out.println(Content size: sb.length());}}
} Java代理非常适合解决此类挑战。 我们只需要定义一个转换器即可通过注入代码以将输出生成到控制台来稍微修改sun.net.www.protocol.http.HttpURLConnection构造函数。 听起来很吓人但是使用ClassFileTransformer和Javassist非常简单。 让我们看一下这样的转换器实现 public class SimpleClassTransformer implements ClassFileTransformer {Overridepublic byte[] transform( final ClassLoader loader, final String className,final Class? classBeingRedefined, final ProtectionDomain protectionDomain,final byte[] classfileBuffer ) throws IllegalClassFormatException {if (className.endsWith(sun/net/www/protocol/http/HttpURLConnection)) {try {final ClassPool classPool ClassPool.getDefault();final CtClass clazz classPool.get(sun.net.www.protocol.http.HttpURLConnection);for (final CtConstructor constructor: clazz.getConstructors()) {constructor.insertAfter(System.out.println(this.getURL()););}byte[] byteCode clazz.toBytecode();clazz.detach();return byteCode;} catch (final NotFoundException | CannotCompileException | IOException ex) {ex.printStackTrace();}}return null;}
} ClassPool和所有CtXxx类 CtClass CtConstructor 都来自Javassist库。 我们所做的转换是非常幼稚的但此处仅用于演示目的。 首先由于我们仅对HTTP通信感兴趣因此sun.net.www.protocol.http.HttpURLConnection是来自标准Java库的类。 请注意而不是“。” 分隔符 className带有“ /”。 其次我们寻找HttpURLConnection类并通过注入System.out.println(this.getURL());修改其所有构造函数System.out.println(this.getURL()); 最后的声明。 最后我们返回了该类转换后的版本的新字节码因此它将由JVM使用而不是原始版本。 这样Java代理的premain方法的作用就是将SimpleClassTransformer类的实例SimpleClassTransformer到检测上下文中 public class SimpleAgent {public static void premain(String agentArgs, Instrumentation inst) {final SimpleClassTransformer transformer new SimpleClassTransformer();inst.addTransformer(transformer);}
} 而已。 看起来很容易同时又有些令人恐惧。 为了完成Java代理我们必须提供适当的MANIFEST.MF以便JVM能够选择正确的类。 这是必需属性的相应最小集合有关更多详细信息请参阅Java Agent Basics部分 Manifest-Version: 1.0
Premain-Class: com.javacodegeeks.advanced.agent.SimpleAgent 这样一来首先的Java代理就准备好进行一场真正的战斗。 在本教程的下一部分中我们将介绍一种与Java应用程序一起运行Java代理的方法。 5.运行Java代理 从命令行运行时可以使用具有以下语义的-javaagent参数将Java代理传递到JVM实例 -javaagent:path-to-jar[options] 其中path-to-jar是查找Java代理JAR归档文件的路径而options包含可以通过agentArgs参数更准确地传递给Java代理的其他选项。 例如从编写您的第一个Java代理 使用Java 7版本部分运行我们的Java代理的命令行如下所示假定代理JAR文件位于当前文件夹中 java -javaagent:advanced-java-part-15-java7.agents-0.0.1-SNAPSHOT.jar 与advanced-java-part-15-java7.agents-0.0.1-SNAPSHOT.jar Java代理一起运行SampleClass类时该应用程序将在控制台上打印所有URL Google和Yahoo! 。尝试使用HTTP协议进行访问其次是Google和Yahoo!搜索主页的内容大小 http://www.google.com
Content size: 20349
http://www.yahoo.com
Content size: 1387 在未指定Java代理的情况下运行相同的SampleClass类将仅在控制台上输出内容大小而不输出URL请注意内容大小可能会有所不同 Content size: 20349
Content size: 1387 JVM使运行Java代理变得简单。 但是请注意任何错误或不正确的字节码生成都可能使JVM崩溃并可能丢失此时您的应用程序可能保存的重要数据。 6.接下来 到最后高级Java教程也结束了。 希望您发现它是有用实用和有趣的。 有许多主题尚未涵盖但是非常欢迎您继续深入探讨Java语言平台生态系统和不可思议的社区的奇妙世界。 祝好运 7.下载源代码 您可以在此处下载本课程的源代码 advanced-java-part-15 翻译自: https://www.javacodegeeks.com/2015/09/java-agents.htmljava代理模式
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/84316.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!