WebSphere sMash(Project Zero)提供 Java Bridge,讓 PHP 腳本直接呼叫 Java 類別、存取欄位、處理例外與型別轉換。本文以 Apache Lucene 為例,示範用 PHP 撰寫索引與搜尋功能,並效能比較 Java Bridge、純 Java、Zend Search Lucene 三種實作。
<?php
$file = new Java("java.io.File", __FILE__, FALSE);
var_dump($file);
var_dump($file->isDirectory());
?>
輸出 Java 物件資訊與方法呼叫結果。
$map = new Java("java.util.HashMap");
$map->put("title", "Java Bridge!");
$array = array(1,2,3,4,5);
$map->put("stuff", $array); // PHP 陣列自動轉為 Java Map
var_dump($map->get("stuff")); // 取回自動轉為 PHP 陣列
$list = new Java("java.util.ArrayList");
$list->add("Java Bridge!");
$list->add(new Java("java.util.Date", 70, 9, 4));
$list->add(array(1,2,3,4,5));
$iter = $list->iterator();
while ($iter->hasNext() == TRUE) {
var_dump($iter->next()); echo "<br/>";
}
$sys = new JavaClass("java.lang.System");
echo "Current time: " . $sys->currentTimeMillis() . "<br/>";
$intClass = new JavaClass("java.lang.Integer");
var_dump($intClass->MIN_VALUE);
try {
$sys = new JavaClass("java.lang.System");
$sys->getProperty(FALSE); // 錯誤參數型別
} catch (JavaException $e) {
echo "Cause: " . $e->getCause();
}
| Java 型別 | PHP 型別 | 備註 |
|---|---|---|
| null | null | |
| Integer/int | int | |
| Double/double | double | |
| Boolean/boolean | bool | |
| Byte/byte | int | |
| Character/char | int | |
| Short/short | int | |
| Long/long | int | |
| Float/float | double | |
| byte[] | string | |
| String | string | 使用執行期編碼 |
| Map | array | 遞迴轉換巢狀 Map |
| Object[] | array | |
| 其他 | Java Bridge Wrapper | 通用 PHP 物件包裝 |
lucene-2.2.0.tar.gz,解壓取出 lucene-core-2.2.0.jar、lucene-demos-2.2.0.jar。Lucene,將 JAR 放入 lib/ 目錄。WebSphere sMash Tools → Resolve 載入類別路徑。表單輸入目錄與副檔名,送出後遞迴索引符合條件檔案:
function index_directory($path, $extension) {
$analyser = new Java("org.apache.lucene.analysis.SimpleAnalyzer");
$policy = new Java("org.apache.lucene.index.KeepOnlyLastCommitDeletionPolicy");
$dir = new JavaClass("org.apache.lucene.store.FSDirectory")
->getDirectory(new Java("java.io.File", INDEX_DIRECTORY, FALSE));
$writer = new Java("org.apache.lucene.index.IndexWriter",
$dir, TRUE, $analyser, TRUE, $policy);
$writer->setUseCompoundFile(FALSE);
$start = microtime(true);
recursive_index_directory($writer, $path, $extension);
$writer->setMaxFieldLength(1000000);
$writer->optimize();
$writer->close();
echo "Indexed " . $writer->docCount() . " docs in " . (microtime(true)-$start) . "s";
}
function recursive_index_directory($writer, $path, $ext) {
$handle = opendir($path);
while (($item = readdir($handle)) !== FALSE) {
if ($item=='.' || $item=='..') continue;
$full = "$path/$item";
if (is_dir($full)) recursive_index_directory($writer, $full, $ext);
elseif (substr(strtolower($full), -strlen($ext)) === $ext)
index_file($writer, $full);
}
closedir($handle);
}
function index_file($writer, $path) {
try {
$doc = new JavaClass("org.apache.lucene.demo.FileDocument")
->Document(new Java("java.io.File", $path, FALSE));
$writer->addDocument($doc);
} catch (JavaException $e) { echo "Skip non-UTF8: $path"; }
}
function search_index($indexDir, $queryStr) {
$searcher = new Java("org.apache.lucene.search.IndexSearcher",
new JavaClass("org.apache.lucene.store.FSDirectory")
->getDirectory(new Java("java.io.File", $indexDir, FALSE)));
$parser = new Java("org.apache.lucene.queryParser.QueryParser",
"contents", new Java("org.apache.lucene.analysis.SimpleAnalyzer"));
$query = $parser->parse($queryStr);
$hits = $searcher->search($query);
for ($i=0; $i<$hits->length(); $i++) {
echo "$i) " . $hits->doc($i)->get("path") . "<br/>";
}
echo "Total hits: " . $hits->length();
}
| 技術 | 耗時 (秒) |
|---|---|
| WebSphere sMash Java Bridge | 9 |
| 純 Java Lucene | 8 |
| Zend Search Lucene (PHP) | 200 |
Java Bridge 僅比純 Java 慢 ~12%,證明 PHP 執行期與 JVM 互動開銷極低。Zend 純 PHP 實作雖慢但無需 Java 環境,適合純 PHP 專案。
JavaSignature 可指定參數型別精確選擇多載:$sig = new JavaSignature(JAVA_STRING);
$str = new Java("java.lang.String", $sig, "Hello World!");
var_dump($str->toLowerCase());
foreach,需手動 iterator() + while。Java Bridge 讓 PHP 專案以極低成本重用成熟 Java 函式庫(Lucene、POI、iText 等)。效能接近原生 Java,開發效率兼具 PHP 簡潔與 Java 強大生態。建議在需要高效能演算法、現有 Java 資產重用的場景採用。