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

企业简介的网站怎么做昆山网站建设公司

企业简介的网站怎么做,昆山网站建设公司,电子商务网站建设需要哪些步骤,马云为啥说2025年房价如葱字节码检测库cglib是许多众所周知的Java框架#xff08;例如Hibernate #xff08;现在不再 #xff09;#xff09;或Spring最受欢迎的选择#xff0c;它们可以完成肮脏的工作。 字节码检测允许在Java应用程序的编译阶段之后操作或创建类。 由于Java类在运行时动态链接例如Hibernate 现在不再 或Spring最受欢迎的选择它们可以完成肮脏的工作。 字节码检测允许在Java应用程序的编译阶段之后操作或创建类。 由于Java类在运行时动态链接因此可以将新类添加到已经运行的Java程序中。 Hibernate例如使用cglib生成动态代理。 Hibernate不会返回您存储在数据库中的完整对象而是会返回存储类的检测版本该版本仅在需要时才从数据库延迟加载某些值。 例如在向方法调用添加安全约束时Spring使用了cglib。 而不是直接调用您的方法Spring安全性将首先检查指定的安全性检查是否通过并且仅在验证之后委托给您的实际方法。 cglib的另一种流行用法是在诸如mockito之类的模拟框架内其中模拟只不过是插装类 在插装类中方法被空的实现加上一些跟踪逻辑所替代。 除了ASM 另一个基于cglib的非常高级的字节码操作库之外cglib还提供了相当低级的字节码转换器即使不了解已编译的Java类的详细信息也可以使用它们。 不幸的是cglib的文档很短并不是说基本上没有。 除了2005年的一篇博客文章演示了Enhancer类之外没有太多可找的了。 这篇博客文章是试图演示cglib及其不幸的是常常尴尬的API。 增强剂 让我们从Enhancer类cglib库中最常用的类开始。 增强程序允许为非接口类型创建Java代理。 可以将Enhancer器与Java标准库的Proxy类在Java 1.3中引入进行比较。 Enhancer动态创建给定类型的子类但拦截所有方法调用。 除Proxy类外它对类和接口类型均适用。 以下示例和下面的一些示例均基于此简单的Java POJO public static class SampleClass {public String test(String input) {return Hello world!;} } 使用cglib可以使用Enhancer和FixedValue回调轻松地将test(String)方法的返回值替换为另一个值 Test public void testFixedValue() throws Exception {Enhancer enhancer new Enhancer();enhancer.setSuperclass(SampleClass.class);enhancer.setCallback(new FixedValue() {Overridepublic Object loadObject() throws Exception {return Hello cglib!;}});SampleClass proxy (SampleClass) enhancer.create();assertEquals(Hello cglib!, proxy.test(null)); } 在上面的示例中增强器将返回SampleClass的已检测子类的实例其中所有方法调用均返回固定值该值是由上面的匿名FixedValue实现生成的。 该对象由Enhancer#create(Object...) 其中该方法采用任意数量的参数这些参数用于选择增强类的任何构造函数。 即使构造函数只是Java字节码级别上的方法 Enhancer类也不能检测构造函数。它也不能检测static或final类。如果只想创建一个类而又不想创建实例 Enhancer#createClass将创建一个Class实例可用于动态创建实例。 增强类的所有构造函数都可以在此动态生成的类中用作委托构造函数。 请注意在上面的示例中将委派任何方法调用还应调用java.lang.Object定义的方法。 结果对proxy.toString()的调用也将返回“ Hello cglib”。 相比之下对proxy.hashCode()的调用将导致ClassCastException因为即使Object#hashCode签名需要原始整数 FixedValue拦截器也始终返回String 。 可以得出的另一个结论是最终方法没有被拦截。 这种方法的一个示例是Object#getClass 在调用该方法时将返回类似“ SampleClass $$ EnhancerByCGLIB $$ e277c63c”的内容。 此类名称由cglib随机生成以避免命名冲突。 在程序代码中使用显式类型时请注意增强型实例的不同类。 但是由cglib生成的类将与增强类位于同一包中因此可以覆盖package-private方法。 与最终方法类似子类化方法导致无法增强最终类。 因此像Hibernate这样的框架无法持久化最终类。 接下来让我们看一个更强大的回调类InvocationHandler 它也可以与Enhancer一起使用 Test public void testInvocationHandler() throws Exception {Enhancer enhancer new Enhancer();enhancer.setSuperclass(SampleClass.class);enhancer.setCallback(new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {if(method.getDeclaringClass() ! Object.class method.getReturnType() String.class) {return Hello cglib!;} else {throw new RuntimeException(Do not know what to do.);}}});SampleClass proxy (SampleClass) enhancer.create();assertEquals(Hello cglib!, proxy.test(null));assertNotEquals(Hello cglib!, proxy.toString()); } 该回调使我们可以对调用的方法进行回答。 但是在InvocationHandler#invoke方法随附的代理对象上调用方法时应小心。 将使用相同的InvocationHandler调度对此方法的所有调用因此可能导致无限循环。 为了避免这种情况我们可以使用另一个回调分配器 Test public void testMethodInterceptor() throws Exception {Enhancer enhancer new Enhancer();enhancer.setSuperclass(SampleClass.class);enhancer.setCallback(new MethodInterceptor() {Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable {if(method.getDeclaringClass() ! Object.class method.getReturnType() String.class) {return Hello cglib!;} else {proxy.invokeSuper(obj, args);}}});SampleClass proxy (SampleClass) enhancer.create();assertEquals(Hello cglib!, proxy.test(null));assertNotEquals(Hello cglib!, proxy.toString());proxy.hashCode(); // Does not throw an exception or result in an endless loop. } MethodInterceptor允许完全控制所拦截的方法并提供一些实用程序来以其原始状态调用增强类的方法。 但是为什么仍然要使用其他方法呢 因为其他方法效率更高并且cglib通常用于效率起着重要作用的边缘案例框架。 MethodInterceptor的创建和链接需要例如生成不同类型的字节码以及创建InvocationHandler不需要的某些运行时对象。 因此可以将其他类与增强器一起使用 LazyLoader 即使LazyLoader的唯一方法具有相同的方法签名FixedValue的LazyLoader是在根本不同FixedValue拦截。 LazyLoader实际上应该返回增强类的子类的实例。 仅当在增强型对象上调用方法并将其存储以供将来调用生成的代理时才请求此实例。 如果您的对象创建昂贵而又不知道该对象是否会被使用则这是有道理的。 请注意必须同时为代理对象和延迟加载的对象调用增强类的某些构造函数。 因此请确保有另一个廉价的可能protected 构造函数可用或将接口类型用作代理。 您可以通过将参数提供给Enhancer#create(Object...)来选择构造的被调用方法。 Dispatcher Dispatcher类似于LazyLoader但将在每次方法调用时调用而不存储已加载的对象。 这允许更改类的实现而无需更改对它的引用。 同样请注意必须同时为代理和生成的对象调用某些构造函数。 ProxyRefDispatcher 此类包含对在其签名中调用的代理对象的引用。 例如这允许将方法调用委托给此代理的另一个方法。 请注意如果从ProxyRefDispatcher#loadObject(Object)内调用相同的方法这很容易导致无限循环并且始终会导致无限循环。 NoOp NoOp类与其名称不符。 而是将每个方法调用委派给增强类的方法实现。 此时最后两个拦截器可能对您没有意义。 当总是将方法调用始终委派给增强类时为什么还要增强类呢 你是对的。 这些拦截器仅应与CallbackFilter一起使用如以下代码片段所示 Test public void testCallbackFilter() throws Exception {Enhancer enhancer new Enhancer();CallbackHelper callbackHelper new CallbackHelper(SampleClass.class, new Class[0]) {Overrideprotected Object getCallback(Method method) {if(method.getDeclaringClass() ! Object.class method.getReturnType() String.class) {return new FixedValue() {Overridepublic Object loadObject() throws Exception {return Hello cglib!;};}} else {return NoOp.INSTANCE; // A singleton provided by NoOp.}}};enhancer.setSuperclass(MyClass.class);enhancer.setCallbackFilter(callbackHelper);enhancer.setCallbacks(callbackHelper.getCallbacks());SampleClass proxy (SampleClass) enhancer.create();assertEquals(Hello cglib!, proxy.test(null));assertNotEquals(Hello cglib!, proxy.toString());proxy.hashCode(); // Does not throw an exception or result in an endless loop. } Enhancer实例在其Enhancer#setCallbackFilter(CallbackFilter)方法中接受CallbackFilter在此方法中它希望将增强类的方法映射到Callback实例数组的数组索引。 在创建的代理上调用方法时 Enhancer将选择相应的拦截器并将调用的方法分派到相应的Callback 这是到目前为止引入的所有拦截器的标记接口。 为了使该API不再那么笨拙cglib提供了一个CallbackHelper 它将代表一个CallbackFilter并可以为您创建一个Callback数组。 上面的增强对象在功能上与MethodInterceptor示例中的对象等效但是它使您可以编写专用的拦截器同时将对这些拦截器的调度逻辑分开。 它是如何工作的 Enhancer创建类时它将为创建后为增强类注册为Callback每个拦截器设置一个创建private static字段。 这也意味着用cglib创建的类定义在创建后就不能重用因为回调的注册不会成为所生成类的初始化阶段的一部分而是由JVM初始化该类后由cglib手动准备的。 这也意味着用cglib创建的类在初始化后在技术上还没有准备好例如由于目标计算机中加载的类不存在回调因此无法通过电线发送。 取决于注册拦截器CGLIB可能记录附加字段诸如例如用于MethodInterceptor其中两个private static字段一个保持的反射Method和另一保持MethodProxy是在增强类或任何的截取的每方法注册它的子类。 请注意 MethodProxy过度使用了FastClass 这会触发其他类的创建下面将对其进行详细描述。 由于所有这些原因使用Enhancer时要小心。 并且始终要防御性地注册回调类型因为例如MethodInterceptor将触发创建其他类并在增强类中注册其他static字段。 这特别危险因为回调变量也作为static变量存储在增强的类中这意味着回调实例永远不会被垃圾回收除非它们的ClassLoader是异常的。 当使用匿名类对它们的外部类进行静默引用时这特别危险。 回想一下上面的例子 Test public void testFixedValue() throws Exception {Enhancer enhancer new Enhancer();enhancer.setSuperclass(SampleClass.class);enhancer.setCallback(new FixedValue() {Overridepublic Object loadObject() throws Exception {return Hello cglib!;}});SampleClass proxy (SampleClass) enhancer.create();assertEquals(Hello cglib!, proxy.test(null)); } FixedValue的匿名子类几乎无法从增强的SampleClass引用因此匿名的FixedValue实例或包含Test方法的类都不会被垃圾回收。 这会在您的应用程序中引入讨厌的内存泄漏。 因此请勿将非static内部类与cglib一起使用。 为了使示例简短我仅在此博客条目中使用它们。 最后永远不要拦截Object#finalize() 。 由于cglib的子类化方法截取finalize函数是通过覆盖它来实现的通常这是一个坏主意 。 拦截终结器的增强型实例将由垃圾收集器以不同的方式处理并且还将导致这些对象在JVM的终结器队列中排队。 另外如果您偶然在截获的finalize调用中创建了对增强类的硬引用则实际上已经创建了一个不可收集的实例。 通常这不是您想要的。 请注意 final方法永远不会被cglib拦截。 因此 Object#wait Object#notify和Object#notifyAll不会带来相同的问题。 但是请注意 Object#clone可能会被拦截这是您可能不想执行的操作。 不变的豆 cglib的ImmutableBean允许您创建一个不可变包装器类似于Collections#immutableSet 。 IllegalStateException 但是不是Java API建议的UnsupportedOperationException可以防止对基础bean进行所有更改。 看着一些豆 public class SampleBean {private String value;public String getValue() {return value;}public void setValue(String value) {this.value value;} } 我们可以使这个bean不可变 Test(expected IllegalStateException.class) public void testImmutableBean() throws Exception {SampleBean bean new SampleBean();bean.setValue(Hello world!);SampleBean immutableBean (SampleBean) ImmutableBean.create(bean);assertEquals(Hello world!, immutableBean.getValue());bean.setValue(Hello world, again!);assertEquals(Hello world, again!, immutableBean.getValue());immutableBean.setValue(Hello cglib!); // Causes exception. } 从该示例可以明显看出不可变bean通过抛出IllegalStateException防止所有状态更改。 但是可以通过更改原始对象来更改Bean的状态。 所有这些更改都将通过ImmutableBean反映出来。 豆产生器 BeanGenerator是cglib的另一个bean实用程序。 它将在运行时为您创建一个bean Test public void testBeanGenerator() throws Exception {BeanGenerator beanGenerator new BeanGenerator();beanGenerator.addProperty(value, String.class);Object myBean beanGenerator.create();Method setter myBean.getClass().getMethod(setValue, String.class);setter.invoke(myBean, Hello cglib!);Method getter myBean.getClass().getMethod(getValue);assertEquals(Hello cglib!, getter.invoke(myBean)); } 从该示例可以明显BeanGenerator BeanGenerator首先将一些属性用作名称/值对。 创建时 BeanGenerator创建访问器 type getname() void setname(type) 为了你。 当另一个库期望通过反射来解析的bean但是您在运行时不知道这些bean时这可能很有用。 一个示例是Apache Wicket 它可以与bean一起使用。 豆复印机 BeanCopier是另一个Bean实用程序可通过其属性值复制Bean。 考虑另一个具有与SampleBean相似的属性的bean public class OtherSampleBean {private String value;public String getValue() {return value;}public void setValue(String value) {this.value value;} } 现在您可以将属性从一个bean复制到另一个 Test public void testBeanCopier() throws Exception {BeanCopier copier BeanCopier.create(SampleBean.class, OtherSampleBean.class, false);SampleBean bean new SampleBean();myBean.setValue(Hello cglib!);OtherSampleBean otherBean new OtherSampleBean();copier.copy(bean, otherBean, null);assertEquals(Hello cglib!, otherBean.getValue()); } 不受特定类型的限制。 BeanCopier#copy方法可以最终选择一个Converter 它允许对每个bean属性进行一些进一步的操作。 如果BeanCopier是使用false作为第三个构造函数参数创建的则Converter被忽略因此可以为null 。 散装豆 BulkBean允许通过数组而不是方法调用使用一组指定的bean访问器 Test public void testBulkBean() throws Exception {BulkBean bulkBean BulkBean.create(SampleBean.class,new String[]{getValue},new String[]{setValue},new Class[]{String.class});SampleBean bean new SampleBean();bean.setValue(Hello world!);assertEquals(1, bulkBean.getPropertyValues(bean).length);assertEquals(Hello world!, bulkBean.getPropertyValues(bean)[0]);bulkBean.setPropertyValues(bean, new Object[] {Hello cglib!});assertEquals(Hello cglib!, bean.getValue()); } BulkBean将getter名称数组setter名称数组和属性类型数组作为其构造函数参数。 然后可以通过BulkBean#getPropertyBalues(Object)将生成的检测类提取为数组。 同样可以通过BulkBean#setPropertyBalues(Object, Object[])设置bean的属性。 豆地图 这是cglib库中的最后一个bean实用程序。 BeanMap将bean的所有属性转换为String to- Object Java Map Test public void testBeanGenerator() throws Exception {SampleBean bean new SampleBean();BeanMap map BeanMap.create(bean);bean.setValue(Hello cglib!);assertEquals(Hello cglib, map.get(value)); } 另外 BeanMap#newInstance(Object)方法允许通过重用相同的Class为其他bean创建映射。 重点工厂 KeyFactory工厂允许动态创建由多个值组成的键这些值可以在例如Map实现中使用。 为此 KeyFactory需要一些接口来定义应在此类键中使用的值。 此接口必须包含一个名为newInstance的方法该方法返回Object 。 例如 public interface SampleKeyFactory {Object newInstance(String first, int second); } 现在可以通过以下方式创建一个aa密钥的实例 Test public void testKeyFactory() throws Exception {SampleKeyFactory keyFactory (SampleKeyFactory) KeyFactory.create(Key.class);Object key keyFactory.newInstance(foo, 42);MapObject, String map new HashMapObject, String();map.put(key, Hello cglib!);assertEquals(Hello cglib!, map.get(keyFactory.newInstance(foo, 42))); } KeyFactory将确保Object#equals(Object)和Object#hashCode方法的正确实现以便可以在Map或Set使用生成的键对象。 在cglib库中 KeyFactory在内部也有很多使用。 混合蛋白 有些人可能已经从其他编程语言例如Ruby或Scala其中mixin称为特征中了解了Mixin类的概念。 cglib Mixin允许将多个对象组合成一个对象。 但是为此这些对象必须由接口支持 public interface Interface1 {String first(); }public interface Interface2 {String second(); }public class Class1 implements Interface1 {Overridepublic String first() {return first;} }public class Class2 implements Interface2 {Overridepublic String second() {return second;} } 现在可以通过其他接口将Class1和Class2类合并为一个类 public interface MixinInterface extends Interface1, Interface2 { /* empty */ }Test public void testMixin() throws Exception {Mixin mixin Mixin.create(new Class[]{Interface1.class, Interface2.class,MixinInterface.class}, new Object[]{new Class1(), new Class2()});MixinInterface mixinDelegate (MixinInterface) mixin;assertEquals(first, mixinDelegate.first());assertEquals(second, mixinDelegate.second()); } 诚然 Mixin API相当笨拙因为它需要用于Mixin的类来实现某些接口以便非仪表Java也可以解决该问题。 字符串切换器 StringSwitcher将String模拟为int Java Map Test public void testStringSwitcher() throws Exception {String[] strings new String[]{one, two};int[] values new int[]{10, 20};StringSwitcher stringSwitcher StringSwitcher.create(strings, values, true);assertEquals(10, stringSwitcher.intValue(one));assertEquals(20, stringSwitcher.intValue(two));assertEquals(-1, stringSwitcher.intValue(three)); } StringSwitcher允许在String上模拟switch命令例如自Java 7起就可以使用内置的Java switch语句来实现。如果在Java 6或更低StringSwitcher中使用StringSwitcher确实为您的代码增加了好处但是仍然值得怀疑我会个人不建议使用它。 接口制造商 InterfaceMaker会执行其名称所建议的操作它动态创建一个新接口。 Test public void testInterfaceMaker() throws Exception {Signature signature new Signature(foo, Type.DOUBLE_TYPE, new Type[]{Type.INT_TYPE});InterfaceMaker interfaceMaker new InterfaceMaker();interfaceMaker.add(signature, new Type[0]);Class iface interfaceMaker.create();assertEquals(1, iface.getMethods().length);assertEquals(foo, iface.getMethods()[0].getName());assertEquals(double.class, iface.getMethods()[0].getReturnType()); } 除了cglib的任何其他公共API类之外接口制造商还依赖于ASM类型。 在运行的应用程序中创建接口几乎没有意义因为接口仅表示一种类型编译器可以使用该类型来检查类型。 但是当您生成要在以后的开发中使用的代码时这可能很有意义。 方法委托 通过将方法调用绑定到某个接口 MethodDelegate可以将C#类的委托模拟为特定方法。 例如以下代码会将SampleBean#getValue方法绑定到委托 public interface BeanDelegate {String getValueFromDelegate(); }Test public void testMethodDelegate() throws Exception {SampleBean bean new SampleBean();bean.setValue(Hello cglib!);BeanDelegate delegate (BeanDelegate) MethodDelegate.create(bean, getValue, BeanDelegate.class);assertEquals(Hello world!, delegate.getValueFromDelegate()); } 但是有一些注意事项 工厂方法MethodDelegate#create恰好将一个方法名称作为第二个参数。 这是MethodDelegate将为您代理的方法。 必须有一个没有为对象定义参数的方法该方法作为第一个参数提供给工厂方法。 因此 MethodDelegate强度不如可能强。 第三个参数必须是仅包含一个参数的接口。 MethodDelegate实现此接口并且可以MethodDelegate为该接口。 调用该方法时它将在作为第一个参数的对象上调用代理方法。 此外请考虑以下缺点 cglib为每个代理创建一个新类。 最终这会浪费您永久的一代堆空间 您不能代理带有参数的方法。 如果您的接口带有参数则在没有引发异常的情况下方法委托将根本无法工作返回值始终为null 。 如果您的接口需要其他返回类型即使是更通用的返回类型则将收到IllegalArgumentException 。 组播代表 MulticastDelegate工作方式与MethodDelegate略有不同即使它的目标是相似的功能。 为了使用MulticastDelegate 我们需要一个实现接口的对象 public interface DelegatationProvider {void setValue(String value); }public class SimpleMulticastBean implements DelegatationProvider {private String value;public String getValue() {return value;}public void setValue(String value) {this.value value;} } 基于此接口支持的bean我们可以创建一个MulticastDelegate 将对setValue(String)所有调用分派到实现DelegationProvider接口的几个类 Test public void testMulticastDelegate() throws Exception {MulticastDelegate multicastDelegate MulticastDelegate.create(DelegatationProvider.class);SimpleMulticastBean first new SimpleMulticastBean();SimpleMulticastBean second new SimpleMulticastBean();multicastDelegate multicastDelegate.add(first);multicastDelegate multicastDelegate.add(second);DelegatationProvider provider (DelegatationProvider)multicastDelegate;provider.setValue(Hello world!);assertEquals(Hello world!, first.getValue());assertEquals(Hello world!, second.getValue()); } 再次有一些缺点 对象需要实现单方法接口。 这对于第三方库来说很糟糕并且当您使用CGlib进行某些魔术操作 该魔术暴露于常规代码时很尴尬。 另外您可以轻松实现自己的委托尽管没有字节码但我怀疑您在手动委托方面是否能赢得如此之多。 当您的代表返回一个值时您将仅收到您添加的最后一个代表的值。 所有其他返回值都将丢失但在某些时候由多播委托检索。 建设者代表 ConstructorDelegate允许创建字节仪表工厂方法 。 为此我们首先需要一个具有单一方法newInstance的接口该方法返回一个Object并采用任意数量的参数以用于指定类的构造函数调用。 例如为了为SampleBean创建一个ConstructorDelegate 我们需要以下代码来调用SampleBean的默认无参数构造函数 public interface SampleBeanConstructorDelegate {Object newInstance(); }Test public void testConstructorDelegate() throws Exception {SampleBeanConstructorDelegate constructorDelegate (SampleBeanConstructorDelegate) ConstructorDelegate.create(SampleBean.class, SampleBeanConstructorDelegate.class);SampleBean bean (SampleBean) constructorDelegate.newInstance();assertTrue(SampleBean.class.isAssignableFrom(bean.getClass())); }平行分选机 当对数组数组进行排序时 ParallelSorter声称是Java标准库的数组排序器的更快替代方法 Test public void testParallelSorter() throws Exception {Integer[][] value {{4, 3, 9, 0},{2, 1, 6, 0}};ParallelSorter.create(value).mergeSort(0);for(Integer[] row : value) {int former -1;for(int val : row) {assertTrue(former val);former val;}} } ParallelSorter接受一个数组数组并允许对数组的每一行应用合并排序或快速排序。 使用时请小心 当使用基本数组时您必须在示例中调用具有明确排序范围的合并排序例如 ParallelSorter.create(value).mergeSort(0, 0, 3) 否则 ParallelSorter出现一个很明显的错误即试图将原始数组转换为Object[]数组将导致ClassCastException 。 如果数组行不均匀则第一个参数将确定要考虑的行的长度。 不均匀的行将导致不考虑多余的值进行排序或者导致ArrayIndexOutOfBoundException 。 就我个人而言我怀疑ParallelSorter确实具有时间优势。 诚然我还没有尝试对其进行基准测试。 如果您尝试过很高兴在评论中听到它。 快速班和快速成员 通过包装Java类并提供与反射API类似的方法 FastClass承诺比Java反射API更快地调用方法 Test public void testFastClass() throws Exception {FastClass fastClass FastClass.create(SampleBean.class);FastMethod fastMethod fastClass.getMethod(SampleBean.class.getMethod(getValue));MyBean myBean new MyBean();myBean.setValue(Hello cglib!);assertTrue(Hello cglib!, fastMethod.invoke(myBean, new Object[0])); } 除了演示的FastMethod FastClass还可以创建FastConstructor但不能创建快速字段。 但是FastClass如何比正常反射更快 Java反射由JNI执行其中方法调用由某些C代码执行。 FastClass创建一些字节代码这些代码直接从JVM内部调用该方法。 但是HotSpot JVM的较新版本可能还有许多其他现代JVM都知道一个称为膨胀的概念在该概念中当反射方法经常执行时JVM会将反射方法调用转换为FastClass 本机版本 。 您甚至可以通过将sun.reflect.inflationThreshold属性设置为较低的值来控制此行为至少在HotSpot JVM上。 默认值为15。此属性确定在执行了几次反射调用后应使用字节码检测版本替换JNI调用。 因此我建议不要在现代JVM上使用FastClass 但是它可以调整旧Java虚拟机上的性能。 cglib代理 cglib Proxy是本文开头提到的Java Proxy类的重新实现。 它旨在允许在Java 1.3之前的Java版本中使用Java库的代理并且仅在次要细节上有所不同。 但是可以在Java标准库的Proxy javadoc中找到cglib Proxy的更好文档其中提供了其用法示例。 因此我将在这里跳过对cglib Proxy的更详细的讨论。 最后的警告 在对cglib功能进行了概述之后我想说最后一个警告。 所有cglib类都会生成字节码这会导致其他类存储在JVM内存的特殊部分中所谓的烫发空间。 顾名思义该永久空间用于通常不收集垃圾的永久对象。 但是这不是完全正确的加载Class 在加载的ClassLoader可用于垃圾回收之前无法将其卸载。 仅在用自定义ClassLoader加载Class的情况下该ClassLoader不是本机JVM系统ClassLoader 。 这个ClassLoader可以如果本身都被垃圾收集Class ES IT不断加载并且所有的所有实例Class ES IT负载曾经成为可进行垃圾回收。 这意味着如果您在Java应用程序的整个生命周期中创建了越来越多的类并且如果您不注意删除这些类那么您将早晚运行烫发空间这将导致您的应用程序因运行失败而死亡。 OutOfMemoryError手中 。 因此请谨慎使用cglib。 但是如果您明智且谨慎地使用cglib则可以用它做真正令人惊奇的事情这超出了非仪器化Java应用程序可以做的事情。 最后在创建依赖cglib的项目时考虑到它的普及性您应该意识到cglib项目没有得到应有的维护和活动。 缺少的文档是第一个提示。 通常是一团糟的公共API。 但是随后也有将cglib部署到Maven Central的问题。 邮件列表的读取就像垃圾邮件的存档一样。 并且释放周期相当不稳定。 因此您可能想看看javassist 它是cglib的唯一真正的低级替代品。 Javassist捆绑了一个伪Java编译器该编译器甚至无需了解Java字节代码就可以创建非常惊人的字节代码工具。 如果您想弄脏手您可能还喜欢在cglib之上构建的ASM 。 ASM附带了有关库和Java类文件及其字节码的出色文档。 参考 cglib JCG合作伙伴 Rafael Winterhalter在My daily Java博客上缺少的手册 。 翻译自: https://www.javacodegeeks.com/2013/12/cglib-the-missing-manual.html
http://www.zqtcl.cn/news/746870/

相关文章:

  • 网站建设的成本有哪些内容怎么样制作网页
  • 怎么做网站的seo排名知乎茂名网站制作公司
  • 建安证查询网站官方网站建设对比
  • 关于医院要求建设网站的请示市场推广12种推广渠道
  • php做不了大型网站深圳公司注册网址官方
  • 网站副标题怎么写杭州抖音代运营
  • 网站建设基本资料网站数据库连接出错
  • 娄底网站开发温州seo排名公司
  • 成都有哪些网站开发公司最新网推项目
  • 分享公众号的网站小型企业类网站开发公司
  • 青岛网站建设方案案例wordpress主题模板 国人
  • 哪家高端网站建设好贷款织梦网站模板
  • 北京网站建设公司价格最近中文字幕2018免费版2019
  • 帮人做设计的网站自己怎么做新闻开头视频网站
  • 网站开发搜索功能中国建设银行ie下载网站
  • 中山网站建设 骏域网站的形式有哪些
  • 深圳企业网站重庆建站塔山双喜
  • 征婚网站 女 做茶叶生意企业网站推广服务协议
  • 安徽省住房城乡建设厅网站官网英语机构网站建设方案
  • 电商建站价格深圳龙岗建站公司
  • 可以下载源程序的网站.htaccess wordpress
  • 国内优秀设计网站小程序推广方案
  • 网站构建是什么意思怎么做网站盗号
  • 学校网站建设行业现状wordpress怎么保存图片
  • 网站 框架网页建设title:(网站建设)
  • 素材网站推广方案安卓端开发
  • 网站制作可以询价么168推广
  • 河南城乡和住房建设厅网站网络营销的主要特点有哪些
  • 哪些网站可以做自媒体wordpress 左侧
  • joomla! 1.5 网站建设基础教程丹阳网站推广