游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Java源代码动态编译类加载和代码执行(Java8)

  头条创作挑战赛
  Java的一个重要特性是动态的类加载机制。通过在运行时动态地加载类,Java程序可以实现很多强大的功能。下面通过一个具体的实例来说明Java程序中,如何动态地编译Java源代码、加载类和执行类中的代码。这里的代码示例适用的版本是Java8。
  示例所实现的功能很简单,就是对表达式求值。输入的是类似11或3(23)这样的表达式,返回的是表达式的值。示例的做法是动态创建一个Java源文件,编译该文件生成class文件,加载class文件之后再执行。比如,需要求值的表达式是11,那么所生成的Java源文件如下所示,其中11的部分是动态的。publicclassCalculator{publicstaticObjectcalculate(){return11;}}
  我们只需要编译该源文件,加载编译之后的class文件,再通过反射API来调用其中的calculate方法就可以得到表达式求值的结果。编译
  第一步是动态生成Java源代码并编译。生成Java源代码比较简单,直接用字符串连接就可以了。当然了,在生成逻辑比较复杂时,推荐的做法是使用字符串模板引擎,如Handlebars。在下面的代码中,getJavaSource方法生成Java源代码,compile方法进行编译。
  在进行编译的时候,使用的是JDK标准的JavaCompiler接口。从源代码字符串中创建了一个JavaFileObject对象作为编译时的源代码单元。编译时的选项d指定了编译结果的输出路径,这里是一个临时文件夹。compile方法的返回值是一个Pair对象,包含了class文件的路径,以及随机生成的Java包的名称。publicclassDynamicCompilation{privatestaticfinalStringCLASSNAMECalculator;publicstaticPairPath,Stringcompile(Stringexpr)throwsIOException{StringpackageNamezUUID。randomUUID()。toString()。replace(,);PathoutputPathFiles。createTempDirectory(expr);JavaCompilercompilerToolProvider。getSystemJavaCompiler();StandardJavaFileManagerfileManagercompiler。getStandardFileManager(null,null,null);compiler。getTask(null,fileManager,null,ImmutableList。of(d,outputPath。toAbsolutePath()。toString()),null,Collections。singletonList(newStringContentJavaFileObject(CLASSNAME,getJavaSource(packageName,expr))))。call();returnPair。of(outputPath,packageName。CLASSNAME);}privatestaticStringgetJavaSource(StringpackageName,Stringexpr){returnpackagepackageName;publicclassCLASSNAME{publicstaticObjectcalculate(){returnexpr;}};}}
  上面的代码用到了一个帮助类StringContentJavaFileObject,表示从字符串创建的JavaFileObject对象。publicclassStringContentJavaFileObjectextendsSimpleJavaFileObject{privatefinalStringcontent;publicStringContentJavaFileObject(Stringname,Stringcontent){super(URI。create(string:nameKind。SOURCE。extension),Kind。SOURCE);this。contentcontent;}OverridepublicCharSequencegetCharContent(booleanignoreEncodingErrors){returncontent;}}
  加载
  编译完成之后的第二步是动态加载类。这一步并没有实现自定义的类加载器,而且使用内置的系统类加载器。系统类加载器通过ClassLoader。getSystemClassLoader()方法来获取。系统类加载器在classpath上查找类。这里用了一个比较hack的技巧来动态修改系统类加载器的classpath。
  在下面的代码中,ClasspathUpdater的addPath方法可以把一个Path对象表示的路径,添加到系统类加载器的查找路径中。这是因为系统类加载器自身是URLClassLoader类型的加载器,其中的addURL方法可以添加新的查找路径。只不过addURL方法是protected,这里通过反射API来进行调用。publicclassClasspathUpdater{publicstaticvoidaddPath(Pathpath){URLClassLoaderclassLoader(URLClassLoader)ClassLoader。getSystemClassLoader();try{MethodmethodURLClassLoader。class。getDeclaredMethod(addURL,URL。class);method。setAccessible(true);method。invoke(classLoader,path。toUri()。toURL());}catch(Exceptione){thrownewRuntimeException(e);}}}
  上面介绍的ClasspathUpdater类中的使用技巧,只对Java8生效。在Java9引入模块系统时,对系统类加载器进行了修改。系统类加载器被替换成了应用类加载器。应用类加载器不再是URLClassLoader类型了,就不能使用这个技巧了。执行
  最后一步就是执行动态加载的Java类。这一步比较简单,只需要用Class。forName方法来查找Java类,再找到对应的Method对象,直接调用即可。下面的代码给出了示例。publicclassInvoker{publicstaticObjectinvoke(StringclassName){try{MethodmethodClass。forName(className)。getDeclaredMethod(calculate);returnmethod。invoke(null);}catch(Exceptione){thrownewRuntimeException(e);}}}完整的执行过程
  最后把整个流程串起来。在下面的代码中,需要求值的表达式是(11)35。0。首先调用DynamicCompilation。compile方法进行动态编译,得到class文件的路径和完整的类名。class文件的路径通过ClasspathUpdater。addPath方法添加到classpath中。完整的类名则传递给Invoker。invoke方法来执行。最后输出的结果是表达式的值。publicclassMain{publicstaticvoidmain(String〔〕args)throwsIOException{PairPath,StringresultDynamicCompilation。compile((11)35。0);ClasspathUpdater。addPath(result。getLeft());System。out。println(Invoker。invoke(result。getRight()));}}

iFixit完整拆解苹果MacBookPro16英寸2021IT之家10月30日消息,据9to5Mac、MacRumors报道,在对新MacBookPro2021的初步拆解中,iFixit发现苹果笔记本在可维修性方面有一些改进,如电池没……朝鲜城里姑娘和农村姑娘有什么区别?说到朝鲜,很多人不陌生。说起朝鲜姑娘,很多人觉得漂亮。去朝鲜旅行,我接触到不少朝鲜姑娘。严格意义上来说,我接触到的是平壤姑娘。平壤姑娘美丽大方,谈吐优雅,穿着打扮时髦。朝鲜大部……IT之家评测室大疆手机云台DJIOM4体验一代更比一代强尽管现如今新发布的手机都在强调其影像和防抖性能,但手持云台仍是相当多视频拍摄爱好者、vlog博主的必备装备,手持云台市场老大哥的大疆,其手机云台仍保持着一年一更的频率,8月26……IT之家评测室荣耀手表GSPro评测探索未知,从它开始在9月4日的IFA2020大会上,荣耀全球发布了两款全新系列的智能手表,包括荣耀手表GSPro和荣耀手表ES。前者是荣耀推出的首款智能户外运动手表,支持5ATM级防水,拥有25……早上起得很早本人也是经过了深思熟虑,在每个日日夜夜思考这个问题。博曾经提到过,一次失败,只是证明我们成功的决心还够坚强。维这句话看似简单,但其中的阴郁不禁让人深思。问题的关键究竟为何?迈克……三星手机也搞内存扩展,GalaxyA52s5G最多可获得4GIT之家9月12日消息安卓手机界的最新趋势之一是通过软件更新为设备添加内存扩展功能,现在三星也加入了这个游戏。三星GalaxyA52s5G的最新更新后,加入了一个名为RA……OPPOFindX2将支持最大7GB内存扩展IT之家7月2日消息据外媒gsmarena,OPPO即将为一款旗舰机带来最大7GB的内存扩展。据报道,OPPOFindX2目前已向印度推送2021年6月补丁和CPH202……索尼印度确认PS5数字版延迟发布配件只有DualSense手日前,索尼PlayStation印度官方推特近日发布的信息显示,全新的索尼PS5游戏主机将于当地时间1月12日开始在亚马逊等电商平台以及索尼线下门店开启预售,并将于2月2日正式……索尼推出2020年限定版aibo焦糖色索狗IT之家1月21日消息据索尼官方消息,索尼的自主型娱乐机器人aibo将推出2020年焦糖色限定版,价格为198000日元(约合人民币12403元)。aibo是索尼于199……穹之扉的三个结局,不仅仅是悲剧和完美结局轩辕剑系列游戏在结局这件事情上可以说确实是考虑到了不少玩家的心情啊,他们在很多版本中都设定了多种结局,让玩家有了更多的选择,不至于因为总是悲剧结尾而久久意难平。就拿《穹之……波兰第七大城市什切青,在奥得河下游,是波罗的海沿岸转运港波兰西北部城市什切青面积301平方公里,有50万人口,是波兰西波美拉尼亚省的首府,也是波兰第七大城市。什切青在历史上被波兰、瑞典、丹麦、普鲁士和德国先后统治,直到二战以后……联想即将推出Air15笔记本标配12GB内存1TBSSD,7IT之家9月10日消息据介绍,联想即将在9月18日推出Air15笔记本,搭载10代酷睿处理器和MX250独显,标配12GB内存1TBSSD,价格尚未公布。联想Air15规……
Tile和英特尔合作寻找我的笔记本功能未来可期IT之家5月8日消息美国当地时间周四,蓝牙追踪技术公司Tile和英特尔宣布,两者将进行合作。Tile将把自家的跟踪技术引入笔记本电脑,帮助用户找到它遗落或被盗的PC产品。英特尔……孩子出息了不一定是好事?前几天也看到了有人提这个问题,我觉得这得好好理一理,才能说得清楚,刚好我也有一些想法,所以就写一篇文章吧。与大家交流讨论。孩子长大了,出息了是不是好事?这是有很多因素影响……芝奇推出夜光版焰光戟内存条,断了电也有光IT之家4月1日消息根据芝奇推特官方的消息,夜光版焰光戟内存条现已推出,价格尚未公布。IT之家曾报道,去年10月,由于三星和美光推出了16Gb的新型内存芯片,芝奇也带来了……金士顿台式机笔记本32GB内存上架DDR43200,1499IT之家3月10日消息在CES2020上,金士顿公布了新款的台式机笔记本32GB骇客神条内存,现已上架京东,32GB单条DDR43200,售价1499元。金士顿DDR43……金士顿国内推出32GB内存条,可选36003733MHzIT之家2月28日消息今天,金士顿在微信公众号上宣布推出32GB单条骇客神条,可选36003733MHz,有无光和RGB两个版本。HyperXFURYRGBDDR4……盘点中国各地的特色菜,招牌菜一省一菜,喜欢旅游的人请收藏全国各地不同的饮食习惯,形成了样式丰富的各大菜系和代表菜招牌菜,各色美味多姿多彩,让人流连忘返。俗话说,一方水土,养一方人。下面我为你盘点一下,中国各省市的特色菜,招牌菜……华硕Z490吹雪主板上架银白配色,二次元形象加持IT之家5月6日消息华硕Z490系列主板全系开启预约,价格最高的ROGMAXIMUSXIIEXTREME预售价达到8999元。华硕今年还新增了ROGSTRIXZ490AGAMI……华擎推出Z490ITX主板搭载雷电3,支持基频动态提升IT之家5月6日消息今晚,英特尔Z490系列主板开启预约。华擎现已公布旗下Z490主板的价格,从1199元到8888元不等,其中Z490PhantomGamingITXTB3电……年纪大了看东西模糊,吃叶黄素有用吗?科学用眼很重要生活中不少老年人都出现眼睛功能下降这种情况,在年轻时眼睛明亮,看东西清晰,随着衰老到来以及某些不良用眼习惯影响,看东西逐渐模糊,无论是看书、看报纸还是使用手机都会感觉很费劲。出……华硕发布Z490IITX主板8层PCB,内置智能风扇散热IT之家5月2日消息随着英特尔十代酷睿处理器的发布,主板厂商纷纷更新了旗下的Z490主板,首发产品大部分都是旗舰级的大板。现在,华硕推出了一款ROGSTRIXZ490IGAMI……华硕发布ROGM12E主板16相双8Pin供电,AI智能超频IT之家5月1日消息华硕ROG正式发布了旗下Z490系列主板,至尊旗舰款ROGMAXIMUSXIIEXTREME(简称ROGM12E)采用了16供电模组和ProCoolII高强……华擎推出Z490系列主板非K系列处理器也可超频IT之家5月1日消息华擎现已发布最新的英特尔400系列芯片组主板,包括Z490H470B460以及H410等产品,采用全新一代LGA1200插槽,官方称将伴随着英特尔10核心2……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网