我想在运行时替换一些方法的内容。
我知道我可以为此使用 javassist,但它不起作用,因为我想增强的类已经由系统 classLoader 加载。
如何在运行时替换方法的内容?我应该尝试卸载类(class)吗?我怎样才能做到这一点 ?我看到这是可能的,但我不知道该怎么做。
如果可能,我想避免为此使用外部库,我想自己编写代码。
更多信息: - 我想增强的类包含在一个框架中(在一个 jar 文件中) - 我的代码实际上是这个框架的一个插件 - 我的插件运行的框架有它自己的classLoader,但是这个classLoader不加载它自己的类(它把它们委托(delegate)给系统类加载器) - 我使用的框架是Play。
感谢您的帮助!
最佳答案
您可以使用 Javaassist 以及任何其他字节码工程库来完成。神奇之处在于 Java Attach API,它允许程序附加到正在运行的 JVM(并修改加载的类)。
可以在 com.sun.tools.attach 中找到包,顾名思义,是特定于 Oracle JVM 的。尽管如此,jstack 和 jmap 等 JDK 工具使用它来支持它们的“附加到正在运行的 JVM”功能,因此可以肯定地说它会继续存在。
Attach API 上的文档描述性很强,而这个 Oracle blog post演示在运行时附加代理。一般来说,它归结为:
premain 等以“常规”-javaagent 方式制作重新转换程序premain 重命名为 agentmainAgent-Class 指向您的代理(agentmain-包含)类,并且 可以- Retransform-Classes 设置为 true谢天谢地,API 无需您做太多工作就可以做到这一点,但如果您在运行时生成 JAR,打包代理所需的所有类可能会有点棘手。
我希望包含一个演示代理来演示在运行时附加分析器,但它最终太长而无法发布。尽管如此,我还是把它放在了 Github repo 中。 .
此方法的一个警告 是它使您的程序依赖于 JDK 附带的 tools.jar,而 JRE 中不存在该 tools.jar。您可以通过将 tools.jar 与您的应用程序一起(或在其中提取)来解决此问题,但您仍然需要提供 Attach API 所需的 attach native 库你的申请。我已经在上面链接的存储库中包含了我可以找到的所有平台的库,尽管您也可以自己获取它们。
根据您的用例,这可能是理想的,也可能不是理想的。但它确实有效!
这在问题中并不清楚,但如果您希望在运行时使用您自己的类完全“热交换”一个类,则不需要使用任何字节码操作库。相反,您可以单独编译您的类(确保相同的包、类名等)并在目标上调用 transform 时简单地返回新类的字节类。
关于java - 在运行时替换某些方法的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11749409/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除