Skip to content

zeroibc/php-java

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PHPJava - JVM Emulator by PHP

contributions welcome Compatibility Build Status Total Downloads License: MIT

What is the PHPJava?

The PHPJava is an experimental library which emulates JVM (a.k.a. Java Virtual Machine) by PHP 🐘 The PHPJava reads binary from pre-compiled Java file(s) β˜• This project referred to Java Virtual Machine Specification documentation at the time we made it.

We are welcoming any contributions to this project πŸ’ͺ

Requirements

  • PHP >= 7.2
  • Composer
  • ext-zip

Not currently supported

Sorry, I do not have enough time (T_T)

  • Implements
  • Event
  • Many built-in libraries (ex. java.lang.xxx, java.io.xxx and so on)
  • etc...

Quick start

    1. Install the PHPJava into your project:
$ composer require memory-agape/php-java
    1. Write Java:
class HelloWorld 
{
    public static void main(String[] args)
    {
        System.out.println(args[0] + " " + args[1]);
    }
}
    1. Compile Java:
$ javac -UTF8 /path/to/HelloWorld.java
    1. Call the main method as follows:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

(new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class')))
    ->getInvoker()
    ->getStatic()
    ->getMethods()
    ->call(
        'main',
        ["Hello", 'World']
    );
    1. Get the result
$ php /path/to/HelloWorld.php
Hello World

Java Archive (Execute to *.jar file)

    1. Build your Java files to class. An example is shown below:
$ javac -encoding UTF8 -d build src/*
$ cd build && jar -cvfe ../Test.jar Test *
    1. Execute jar on PHPJava with either an enrtypoint or your targeted method.
<?php
use PHPJava\Core\JavaArchive;

(new JavaArchive('Test.jar'))->execute();

// or
(new JavaArchive('Test.jar'))
    ->getClassByName('Test')
    ->getInvoker()
    ->getStatic()
    ->getMethods()
    ->call(
        'main',
        []
    );

Get/Set static fields

  • ex) Set or Get static fields as follows:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

$staticFieldAccessor = (new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class')))
    ->getInvoker()
    ->getStatic()
    ->getFields();

// Set
$staticFieldAccessor->set('fieldName', 'value');

// Get
echo $staticFieldAccessor->get('fieldName');

Call a static method

  • ex) Call a static method as follows:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

(new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class')))
    ->getInvoker()
    ->getStatic()
    ->getMethods()
    ->call(
        'methodName',
        $firstArgument,
        $secondArgument,
        $thirdArgument,
        ...
    );

// Or if called method have return value then you can store to variable.
$result = (new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class')))
   ->getInvoker()
   ->getStatic()
   ->getMethods()
   ->call(
       'methodWithSomethingReturn',
       $firstArgument,
       $secondArgument,
       $thirdArgument,
       ...
   );

// The $result you want is output.
echo $result;

Get/Set dynamic fields

If you want to get/set dynamic fields, you need to call the construct method on Java by PHPJava.

  • ex) Call dynamic field as follows:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

$javaClass = new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class'));

$javaClass->getInvoker()->construct();

$dynamicFieldAccessor = $javaClass
    ->getInvoker()
    ->getDynamic()
    ->getFields();

// Set
$dynamicFieldAccessor->set('fieldName', 'value');

// Get
echo $dynamicFieldAccessor->get('fieldName');

Call a dynamic method

If you want to get/set dynamic method (same as a field), you need to call the construct method on Java by PHPJava.

  • ex) Call dynamic method as follows:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

$dynamicMethodAccessor = (new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class')))
     ->getInvoker()
     ->construct()
     ->getDynamic()
     ->getMethods(); 

$dynamicMethodAccessor
    ->call(
        'methodName',
        $firstArgument,
        $secondArgument,
        $thirdArgument,
        ...
    );

// Or if called method have return value then you can store to variable.
$dynamicMethodAccessor
   ->call(
       'methodWithSomethingReturn',
       $firstArgument,
       $secondArgument,
       $thirdArgument,
       ...
   );

// The $result you want is output.
echo $result;

Output PHPJava operations

  • Output debug trace as follows if you want to show operation log:
<?php
use PHPJava\Core\JavaClass;
use PHPJava\Core\JavaClassFileReader;

$javaClass = new JavaClass(new JavaClassFileReader('/path/to/HelloWorld.class'));

$javaClass
    ->getInvoker()
    ->getStatic()
    ->getMethods()
    ->call(
        'main',
        ["Hello", 'World']
    );

// Show debug traces.
$javaClass->debug();
  • Output debug trace is shown below:
[method]
public static void main(java.lang.String[])

[code]
<0xb2> <0x00> <0x02> <0x2a> <0x03> <0x32> <0xb6> <0x00> <0x03> <0xb2> <0x00> <0x02> <0x2a> <0x04> <0x32> <0xb6> <0x00> <0x03> <0xb2> <0x00>
<0x02> <0x2a> <0x05> <0x32> <0xb6> <0x00> <0x03> <0xb1>

[executed]
      PC | OPCODE | MNEMONIC             | OPERANDS   | LOCAL STORAGE  
---------+--------+----------------------+------------+-----------------
       0 | 0xB2   | getstatic            | 0          | 1              
       3 | 0x2A   | aload_0              | 1          | 1              
       4 | 0x03   | iconst_0             | 2          | 1              
       5 | 0x32   | aaload               | 3          | 1              
       6 | 0xB6   | invokevirtual        | 2          | 1              
       9 | 0xB2   | getstatic            | 0          | 1              
      12 | 0x2A   | aload_0              | 1          | 1              
      13 | 0x04   | iconst_1             | 2          | 1              
      14 | 0x32   | aaload               | 3          | 1              
      15 | 0xB6   | invokevirtual        | 2          | 1              
      18 | 0xB2   | getstatic            | 0          | 1              
      21 | 0x2A   | aload_0              | 1          | 1              
      22 | 0x05   | iconst_2             | 2          | 1              
      23 | 0x32   | aaload               | 3          | 1              
      24 | 0xB6   | invokevirtual        | 2          | 1              
      27 | 0xB1   | return               | 0          | 1              
---------+--------+----------------------+------------+-----------------
  • [method] shows the called method.
  • [code] shows the JVM's real programs.
  • [executed] shows the executed programs.
    • PC shows the Program Counter.
    • OPCODE shows the Operation Codes.
    • MNEMONIC shows the names of the Operation Codes.
    • OPERANDS shows the stacked items on memory.
    • LOCAL STORAGE shows the stacked items on a method.

PHP problems

  • Problem 1: PHP cannot calculate big numbers because PHP is different from Java. But PHPJava uses bcmath functions and gmp functions to a certain extent to cover such calculations. Therefore, PHPJava returns a mixed value and we recommend to cast them to string on PHPJava.

  • Problem 2: PHPJava cannot completely cover Java types because PHP is different from Java. The comparison table of Java and PHPJava is shown below:

Java PHPJava
null null
boolean \PHPJava\Kernel\Types\_Boolean (including __toString)
char \PHPJava\Kernel\Types\_Char (including __toString), string
byte \PHPJava\Kernel\Types\_Byte (including __toString), string
short \PHPJava\Kernel\Types\_Short (including __toString), string, int
int \PHPJava\Kernel\Types\_Int (including __toString), string, int
long \PHPJava\Kernel\Types\_Long (including __toString), string, int
float \PHPJava\Kernel\Types\_Float (including __toString), string, float
double \PHPJava\Kernel\Types\_Char (including __toString), string, float
  • Problem 3: PHPJava cannot calculate big number of double and float because gmp_pow cannot calculate negative exponents. So, PHPJavas use built-in function pow.

Run unit tests

  • To run a PHPUnit test:
$ ./vendor/bin/phpunit tests
  • To run PHP Coding standards test:
$ ./vendor/bin/phpcs --standard=phpcs.xml src
  • To run all tests:
$ composer run tests

Reference

License

MIT

About

JVM emulator by PHP

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • PHP 100.0%