我正在寻找一种方法,通过重写字节代码并重新加载类来动态添加字段,不确定它是否完全可能。欢迎任何指示。我找到了一些关于修改和加载类的信息,我知道JRebel可以无缝热插拔代码,但不确定这里是否适用相同的方法/工具。
这里的动机是探索理论上更好的替代线程局部对象。如果方法有效,我应该能够用注释替换本地线程,结果应该优于当前的JDK实现。
PS:请救我所有邪恶言论的根源"
澄清用例:
想象一下,我有一个ThreadLocal类:
class A {
ThreadLocal<Counter> counter;
...
counter.get().inc()
}
我想用注释替换它:
class A {
@ThreadLocal
Counter counter;
...
counter.inc()
}
但是代替上面生成的代码,我想改变Thread,以便Thread现在有一个Acounter字段,实际代码将是:
class A {
// Nothing here, field is now in Thread
...
Thread.currentThread().Acounter.inc()
}
答案 0 :(得分:11)
目前,不可能在运行时重新定义类,以便重新定义将导致新的方法或字段。这是因为扫描所有现有实例的堆并转换它们的引用+其引用+潜在的不安全字段偏移基础更新程序(如AtomicFieldUpdater)所涉及的复杂性。
这个限制可以作为JEP-159的一部分解除,但正如并发利益邮件组所讨论的那样,这是一个很大的影响变化,所以可能永远不会发生。
使用Javaassist / similar将允许使用新方法/字段将类转换为新类。此类可以由ClassLoader加载并在运行时使用,但它的定义不会替换现有实例。因此,不可能将此方法与代理结合使用来重新定义类,因为检测重新定义受到限制,因此:“重新定义可能会更改方法主体,常量池和属性。重定义不得添加,删除或重命名字段......“请参阅here。
所以现在,没有。
答案 1 :(得分:5)
答案 2 :(得分:5)
我见过动态重新加载JAR的自定义类加载解决方案 - 您为每个JAR文件定义一个ClassLoader
并使用它从该JAR加载类;要重新加载整个JAR,你只需“杀死”它的ClassLoader
实例并创建另一个实例(在替换JAR文件之后)。
我认为不可能以这种方式调整Java的内部Thread
类,因为您无法控制System ClassLoader
。一个可能的解决方案是使用CustomThreadWeaver
类生成一个新类,其中包含您需要的变量Thread
,并使用自定义DynamicWeavedThreadClassLoader
加载它们。
祝你好运,并在你成功时告诉我们你的怪物; - )
答案 3 :(得分:5)
<强>可能的强> 使用检测,可能还有像javassist这样的库来修改代码。 (但是,目前无法添加和删除字段,方法或构造函数)
var events_array = [{
title: 'Test1',
start: new Date(2015, 09, 14),
tip: 'Personal tip 1',
backgroundColor: 'red'
}, {
title: 'Test2',
start: new Date(2015, 09, 15),
tip: 'Personal tip 2',
backgroundColor: 'green'
}];
不要忘记将//Modify code using javassist and call CtClass#toBytecode() or load bytecode from file
byte[] nevcode;
Class<?> clz = Class.forName("any.class.Example");
instrumentationInstace.redefineClasses(new ClassDefinition(clz, nevcode));
添加到您的java代理的清单中。
真实的例子 - 优化java&lt; 9 Can-Redefine-Classes: true
使用javassist:
string.replace(CharSequence, CharSequence)
答案 4 :(得分:2)
这似乎是使用正确的工具来完成工作的问题。这里也提出了类似的问题:Another Stack Overflow Question和Javaassist字节代码操作库是一种可能的解决方案。
但是没有进一步详细说明为什么会这样做的原因,似乎真正的答案是使用正确的工具来完成工作。例如,使用Groovy the ability to dynamically add methods to the language。
答案 5 :(得分:1)
您可以尝试创建一个使用java.lang.instrument API的JVM代理,更具体地说,使用retransform method“促进已加载类的检测”,然后使用Javassist(或者ASM)如上所述处理字节码。
的更多信息答案 6 :(得分:0)
为了做你想做的事,更简单的替代方法是使用Thread的子类,运行它,然后在该线程内部执行你的例子中的代码(以及currentThread()的强制转换到你的子类)。 / p>
答案 7 :(得分:-2)
您尝试做的事情是不可能的。
由于您已经了解ThreadLocal,因此您已经知道建议的解决方案是什么。
或者,您可以对Thread进行子类并添加自己的字段;但是,只有你明确创建该类的那些线程才会有这些字段,所以你仍然必须能够“退回”#34;使用本地线程。
真正的问题是&#34;为什么?&#34;,如同&#34;为什么本地线程不足以满足您的要求?&#34;