天下网吧 >> 网吧天地 >> 网吧行业 >> 网络追踪 >> 正文

你不知道的Java秘密

2013-10-6ITeye博客佚名
t-by-object视图,及时冻结。根据对象引用草率处理堆可能会非常可笑,您可以通过对总体混乱进行某种自动分析而获得更好的服务。幸运的是,jhat支持OQL语法进行这样的分析。

例如,对所有含有超过100个字符的String运行OQL查询看起来如下:

select s from java.lang.String s where s.count >= 100

结果作为对象链接显示,然后展示该对象的完整内容,字段引用作为可以解除引用的其他链接的其他对象。OQL查询同样可以调用对象的方法,将正则表达式作为查询的一部分,并使用内置查询工具。一种查询工具,referrers()函数,显示了引用指定类型对象的所有引用。下面是寻找所有参考File对象的查询:

select referrers(f) from java.io.File f

您可以查找OQL的完整语法及其在jhat浏览器环境内“OQL Help”页面上的特性。将jhat与OQL相结合是对行为不当的堆进行对象调查的有效方法。

结束语

当您需要近距离观察Java进程内发生的事情时,JDK的分析扩展会非常有用。本文中介绍的所有工具都可以从命令行中由其自己使用。它们还可以与JConsole或VisualVM有力地结合使用。JConsole和VisualVM提供Java虚拟机的总体视图,jstat和jmap等有针对性的工具支持您对研究进行微调。

Java平台上更简单的脚本编写方法

现在,许多Java开发人员都喜欢在Java平台中使用脚本语言,但是使用编译到Java字节码中的动态语言有时是不可行的。在某些情况中,直接编写一个Java应用程序的脚本部分或者在一个脚本中调用特定的Java对象是更快捷、更高效的方法。

这就是javax.script产生的原因了。Java Scripting API是从Java 6开始引入的,它填补了便捷的小脚本语言和健壮的Java生态系统之间的鸿沟。通过使用Java Scripting API,您就可以在您的Java代码中快速整合几乎所有的脚本语言,这使您能够在解决一些很小的问题时有更多可选择的方法。

1.使用jrunscript执行JavaScript

每一个新的Java平台发布都会带来新的命令行工具集,它们位于JDK的bin目录。Java 6也一样,其中jrunscript便是Java平台工具集中的一个不小的补充。

设想一个编写命令行脚本进行性能监控的简单问题。这个工具将借用jmap(见本系列文章前一篇文章中的介绍),每5秒钟运行一个Java进程,从而了解进程的运行状况。一般情况下,我们会使用命令行shell脚本来完成这样的工作,但是这里的服务器应用程序部署在一些差别很大的平台上,包括Windows®和Linux®。系统管理员将会发现编写能够同时运行在两个平台的shell脚本是很痛苦的。通常的做法是编写一个Windows批处理文件和一个UNIX®shell脚本,同时保证这两个文件同步更新。

但是,任何阅读过The Pragmatic Programmer的人都知道,这严重违反了DRY (Don't Repeat Yourself)原则,而且会产生许多缺陷和问题。我们真正希望的是编写一种与操作系统无关的脚本,它能够在所有的平台上运行。

当然,Java语言是平台无关的,但是这里并不是需要使用“系统”语言的情况。我们需要的是一种脚本语言—如,JavaScript。

清单1显示的是我们所需要的简单shell脚本:

清单1. periodic.js

while (true)

{

echo("Hello, world!");

}

由于经常与Web浏览器打交道,许多Java开发人员已经知道了JavaScript(或ECMAScript;JavaScript是由Netscape开发的一种ECMAScript语言)。问题是,系统管理员要如何运行这个脚本?

当然,解决方法是JDK所带的jrunscript实用程序,如清单2所示:

清单2. jrunscript

C:\developerWorks\5things-scripting\code\jssrc>jrunscript periodic.js

Hello, world!

Hello, world!

Hello, world!

Hello, world!

Hello, world!

Hello, world!

Hello, world!

...

注意,您也可以使用for循环按照指定的次数来循环执行这个脚本,然后才退出。基本上,jrunscript能够让您执行JavaScript的所有操作。惟一不同的是它的运行环境不是浏览器,所以运行中不会有DOM。因此,最顶层的函数和对象稍微有些不同。

因为Java 6将Rhino ECMAScript引擎作为JDK的一部分,jrunscript可以执行任何传递给它的ECMAScript代码,不管是一个文件(如此处所示)或是在更加交互式的REPL(“Read-Evaluate-Print-Loop”)shell环境。运行jrunscript就可以访问REPL shell。

2.从脚本访问Java对象

能够编写JavaScript/ECMAScript代码是非常好的,但是我们不希望被迫重新编译我们在Java语言中使用的所有代码—这是违背我们初衷的。幸好,所有使用Java Scripting API引擎的代码都完全能够访问整个Java生态系统,因为本质上一切代码都还是Java字节码。所以,回到我们之前的问题,我们可以在Java平台上使用传统的Runtime.exec()调用来启动进程,如清单3所示:

清单3. Runtime.exec()启动jmap

var p = java.lang.Runtime.getRuntime().exec("jmap", [ "-histo", arguments[0] ])

p.waitFor()

数组arguments是指向传递到这个函数参数的ECMAScript标准内置引用。在最顶层的脚本环境中,则是传递给脚本本身的的参数数组(命令行参数)。所以,在清单3中,这个脚本预期接收一个参数,该参数包含要映射的Java进程的VMID。

除此之外,我们可以利用本身为一个Java类的jmap,然后直接调用它的main()方法,如清单4所示。有了这个方法,我们不需要“传输”Process对象的in/out/err流。

清单4. JMap.main()

var args = [ "-histo", arguments[0] ]

Packages.sun.tools.jmap.JMap.main(args)

Packages语法是一个Rhino ECMAScript标识,它指向已经Rhino内创建的位于核心java.*包之外的Java包。

3.从Java代码调用脚本

从脚本调用Java对象仅仅完成了一半的工作:Java脚本环境也提供了从Java代码调用脚本的功能。这只需要实例化一个ScriptEngine对象,然后加载和评估脚本,如清单5所示:

清单5. Java平台的脚本调用

本文来源:ITeye博客 作者:佚名

声明
声明:本站所发表的文章、评论及图片仅代表作者本人观点,与本站立场无关。文章是出于传递更多信息之目的。若有来源标注错误或侵犯了您的合法权益,请作者持权属证明与本网联系,我们将及时更正、删除,谢谢。 Email:support@txwb.com,系统开号,技术支持,服务联系微信:_WX_1_本站所有有注明来源为天下网吧或天下网吧论坛的原创作品,各位转载时请注明来源链接!
天下网吧·网吧天下
  • 本周热门
  • 本月热门
  • 阅读排行