当前位置: 首页 > wzjs >正文

网站建设方投资成本网页代理免费

网站建设方投资成本,网页代理免费,做网站美工要学什么,做发型的网站欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。 目录 引言避免在性能敏感的热点代码中使用反射缓存反射…

欢迎来到啾啾的博客🐱。
记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。
有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。

目录

  • 引言
  • 避免在性能敏感的热点代码中使用反射
  • 缓存反射对象
  • 使用setAccessible(true)
  • 使用MethodHandle
    • 演示
  • 生成字节码来避免反射

引言

总所周知,反射操作性能开销相对较大。
然而,一些技巧可以显著优化反射操作的性能。

资料引用:Java Reflection, 1000x Faster

避免在性能敏感的热点代码中使用反射

这是最重要的一条原则。因为反射涉及动态类型解析,会阻碍JVM的即时编译(JIT)优化。在需要频繁调用的代码中,应尽量避免使用反射。

缓存反射对象

反射操作中,Class.forName()、Class.getMethod() 和 Class.getField() 这类查找操作非常耗时。如果需要多次对同一个类或方法进行反射操作,应该将查找到的 Class、Method、Field 和 Constructor 对象缓存起来,避免重复查找。

// 不推荐的方式
public void badReflection(Object obj) throws Exception {Method method = obj.getClass().getMethod("doSomething");method.invoke(obj);
}// 推荐的方式:使用Map缓存Method对象
private final Map<String, Method> methodCache = new ConcurrentHashMap<>();public void goodReflection(Object obj) throws Exception {String className = obj.getClass().getName();Method method = methodCache.computeIfAbsent(className, k -> {try {return obj.getClass().getMethod("doSomething");} catch (NoSuchMethodException e) {throw new RuntimeException(e);}});method.invoke(obj);
}

使用setAccessible(true)

当需要调用非公共(private, protected, default)的成员时,必须先调用 setAccessible(true) 来跳过Java语言的访问权限检查。这可以显著提升反射调用的速度。

使用MethodHandle

从Java 7开始引入的 MethodHandle 提供了一种比反射更现代、性能更好的动态方法调用机制。它与反射不同,是“类型化”的,并且可以更好地被JVM优化。
常用于处理处理在编译时未知,在运行时才确定的调用。

和反射区别如下:

特性反射 (java.lang.reflect.Method)方法句柄 (java.lang.invoke.MethodHandle)
本质描述方法元数据的信息类指向方法字节码的直接引用,像函数指针
性能较慢,每次调用都有安全检查和参数解包/打包开销首次查找有开销,后续调用接近原生调用速度,可被JIT优化
类型安全弱类型。invoke(Object, Object…) 接收任意对象,编译时不检查,运行时可能抛出类型转换异常强类型。句柄有明确的 MethodType,调用时如果类型不匹配,编译或运行时会立即失败
安全性每次调用都检查访问权限仅在创建句柄时检查一次访问权限
灵活性API简单直观API更复杂,但提供强大的句柄组合与转换能力
  • MethodHandle:直接指向方法的引用,调用时可以像普通方法一样,并且可以被JIT编译器优化。
  • LambdaMetafactory:结合 MethodHandle 使用,可以创建出实现了特定函数式接口的Lambda实例,其性能几乎等同于直接的方法调用。这种方式在运行时完全避免了反射的开销。

演示

  • 比如在编写框架时,需要根据配置文件来调用某个对象的特定方法。

配置文件(config.json)

{"className": "com.example.UserValidator","methodToCall": "validate"
}

我们的程序它在编译时完全不知道UserValidator这个类,也不知道validate这个方法。
此时可以使用MethodHandle来动态

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;// --- 假设这是用户编写的类 ---
class UserValidator {public boolean validate() {System.out.println("UserValidator is validating...");return true;}
}// --- 这是您编写的框架代码 ---
public class Framework {public void executeFromConfig(Object instance, String methodName) {System.out.println("Framework is about to call method '" + methodName + "' on instance " + instance.getClass().getSimpleName());try {// 1. 获取一个查找上下文MethodHandles.Lookup lookup = MethodHandles.lookup();// 2. 动态确定方法的签名(这里假设是无参,返回boolean)MethodType methodType = MethodType.methodType(boolean.class);// 3. 动态查找方法,得到一个MethodHandle//    这里的 instance.getClass() 和 methodName 都是在运行时才确定的!MethodHandle handle = lookup.findVirtual(instance.getClass(), methodName, methodType);// 4. 调用 handle.invoke() 或 invokeExact()//    这里告诉JVM:请在`instance`这个具体的对象上,执行`handle`所代表的方法。boolean result = (boolean) handle.invoke(instance);System.out.println("Execution result: " + result);} catch (Throwable t) {// 注意:invoke() 和 findVirtual() 都会抛出 Throwablet.printStackTrace();}}public static void main(String[] args) {Framework framework = new Framework();UserValidator userValidatorInstance = new UserValidator();// 框架根据运行时信息(比如配置文件),来调用对象的方法framework.executeFromConfig(userValidatorInstance, "validate");}
}
  • 假设我们有两个不同的类,但我们想用一个统一的框架来处理它们的某个方法
class Greeter {public String sayHello(String name) {return "Hello, " + name;}
}class Calculator {public int add(int a, int b) {return a + b;}
}public class AdvancedFramework {public static void main(String[] args) throws Throwable {MethodHandles.Lookup lookup = MethodHandles.lookup();// --- 场景一:调用 Greeter 的 sayHello 方法 ---Greeter greeter = new Greeter();// 1. 定义方法类型:(String) -> StringMethodType mtHello = MethodType.methodType(String.class, String.class);// 2. 查找句柄MethodHandle mhHello = lookup.findVirtual(Greeter.class, "sayHello", mtHello);// 3. 调用,第一个参数是实例本身,后面是方法的参数String result1 = (String) mhHello.invoke(greeter, "World");System.out.println("Greeter result: " + result1); // 输出: Greeter result: Hello, World// --- 场景二:调用 Calculator 的 add 方法 ---Calculator calculator = new Calculator();// 1. 定义方法类型:(int, int) -> intMethodType mtAdd = MethodType.methodType(int.class, int.class, int.class);// 2. 查找句柄MethodHandle mhAdd = lookup.findVirtual(Calculator.class, "add", mtAdd);// 3. 调用int result2 = (int) mhAdd.invoke(calculator, 10, 20);System.out.println("Calculator result: " + result2); // 输出: Calculator result: 30}
}
  • 适配器模式-绑定参数
    假设你有一个方法对象,但想预先填好它的一个参数,生成一个新的、参数更少的方法对象。这在事件处理等场景中非常有用。
import java.lang.invoke.*;public class BindExample {public void printMessage(String level, String message) {System.out.println("[" + level + "]: " + message);}public static void main(String[] args) throws Throwable {BindExample instance = new BindExample();MethodHandles.Lookup lookup = MethodHandles.lookup();// 原始方法句柄: (BindExample, String, String) -> voidMethodType mt = MethodType.methodType(void.class, String.class, String.class);MethodHandle originalHandle = lookup.findVirtual(BindExample.class, "printMessage", mt);// 我们想创建一个 "INFO" 级别的日志记录器// 使用 bindTo 绑定第一个参数(实例)和第二个参数(level)MethodHandle infoLogger = originalHandle.bindTo(instance).bindTo("INFO");// 新的句柄类型变成了: (String) -> void// 现在调用新的句柄,只需要提供 message 参数infoLogger.invoke("This is an informational message."); // 输出: [INFO]: This is an informational message.// 同样,我们可以创建一个 "ERROR" 级别的日志记录器MethodHandle errorLogger = originalHandle.bindTo(instance).bindTo("ERROR");errorLogger.invoke("A critical error occurred!"); // 输出: [ERROR]: A critical error occurred!}
}

生成字节码来避免反射

对于性能要求极高的场景,例如在框架和库的开发中,可以通过直接生成字节码来避免反射。像 ASM、cglib、Byte Buddy 等库允许在运行时动态创建和修改类。虽然首次生成字节码的开销较大,但一旦生成,其执行速度就和普通的Java代码完全一样,并且可以被JIT充分优化。

字节码增强技术内容有点多,感兴趣的可以看这篇入门。
深入浅出 Byte Buddy:掌握 Java 运行时代码操作的利器

http://www.dtcms.com/wzjs/782461.html

相关文章:

  • dede我的网站深圳网站设计 商城
  • 茂名平安建设网站移动应用开发案例
  • wordpress网站漏洞做自己的网站要多少钱
  • 如何给网站做右侧悬浮电话广州番禺区工商职业技术学校
  • 深圳网站建设服务器超值的网站建设
  • joomla网站模板孟村网站建设价格
  • 郑州汉狮做网站网络公司网站备案密码
  • 微网站开发语言做网站能月入10万
  • 网站开发程序流程图网站开发流程抚州
  • 塘厦做网站杭州公司网站建设
  • 集团高端网站建设最有创意促销活动方案
  • 长沙企业网站排名科普网站建设
  • 长春设计网站个人网店和网站的区别
  • 长春网络传媒做网站骗钱动漫网站建设规划书模板
  • 家具公司网站源码牡丹江建设信息网站
  • 信息化建设网站做网站小程序挣钱吗
  • 网站建设前台和后台设计大兴企业官网网站建设报价
  • 网站建设如何来选择空间东莞热点网站建设
  • 广州物流网站建设上海市企业服务云十问十答
  • 网站怎么做购物车国外 设计网站
  • 一起做英语作业网站crm系统有哪些品牌
  • 建设部网站官网办事大厅广告设计费
  • seo优化文章网站门户建设是什么意思
  • 网站页面设计说明怎么写单页面销售网站
  • 个人网站收款python基础教程怎么样
  • 做网站人家直接百度能搜到的房地产客户管理系统
  • 做网站的人怎么联系厦门市建设厅网站
  • 唐山手机网站建设帮人做网站收多少钱
  • wordpress网站服务器旅行网站模板
  • 工装网站建设方案珠海网站建设推广公司