# PHPJava - JVM Emulator by PHP
[](https://github.com/dwyl/esta/issues)

[](https://travis-ci.org/memory-agape/php-java)
[](https://packagist.org/packages/memory-agape/php-java)
[](https://opensource.org/licenses/MIT)

# What is the PHPJava?
The PHPJava is experimental library which emulate JVM (a.k.a. Java Virtual Machine) by PHP 🐘
The PHPJava proceed to read binary from pre-compiled Java file(s) ☕
This project reference to [Java Virtual Machine Specification](https://docs.oracle.com/javase/specs/jvms/se11/html/index.html) documentation when We makes.
We welcoming to contributions 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
```
- 2) Write Java
```java
class HelloWorld
{
public static void main(String[] args)
{
System.out.println(args[0] + " " + args[1]);
}
}
```
- 3) Compile Java
```
$ javac -UTF8 /path/to/HelloWorld.java
```
- 4) Call to main method as following.
```php
getInvoker()
->getStatic()
->getMethods()
->call(
'main',
["Hello", 'World']
);
```
- 5) Get a result
```
$ php /path/to/HelloWorld.php
Hello World
```
## Java Archive (Execute to *.jar file)
- 1) Build your java files to class. Building example is below.
```
$ javac -encoding UTF8 -d build src/*
$ cd build && jar -cvfe ../Test.jar Test *
```
- 2) execute jar on PHPJava with enrtypoint or your targeted method.
```php
execute();
// or
(new JavaArchive('Test.jar'))
->getClassByName('Test')
->getInvoker()
->getStatic()
->getMethods()
->call(
'main',
[]
);
```
### Get/Set a static fields
- ex) Set or Get a static fields as follows.
```php
getInvoker()
->getStatic()
->getFields();
// Set
$staticFieldAccessor->set('fieldName', 'value');
// Get
echo $staticFieldAccessor->get('fieldName');
```
### Call to a static method
- ex) Call to static method as follows.
```php
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 a dynamic fields
If you want to get/set dynamic fields, you need call to `construct` method on Java by PHPJava.
- ex) Call dynamic field as following.
```php
getInvoker()->construct();
$dynamicFieldAccessor = $javaClass
->getInvoker()
->getDynamic()
->getFields();
// Set
$dynamicFieldAccessor->set('fieldName', 'value');
// Get
echo $dynamicFieldAccessor->get('fieldName');
```
### Call to a dynamic method
If you want to get/set dynamic method (same as field), you need call to `construct` method on Java by PHPJava.
- ex) Call dynamic method as following.
```php
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 following if you want to show operated log.
```php
getInvoker()
->getStatic()
->getMethods()
->call(
'main',
["Hello", 'World']
);
// Show debug traces.
$javaClass->debug();
```
- Outputted debug trace is 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]** is showing called method.
- **[code]** is showing JVM's real programs.
- **[executed]** is showing executed programs.
- **PC** is showing Program Counter.
- **OPCODE** is showing Operation Codes.
- **MNEMONIC** is naming Operation Codes.
- **OPERANDS** is showing stacked items on memory.
- **LOCAL STORAGE** is showing stacked items on a method.
## PHP problems
- **Problem 1:** The PHP is cannot calculating big numbers because of PHP is different to the Java.
But the PHPJava use `bcmath` functions and `gmp` functions to a certain extent to cover to calculate.
The PHPJava return valued is mixed why therefore We recommend to cast to `string` on the PHPJava.
- **Problem 2:** The PHPJava cannot cover to Java's types completely because of PHP is different to the Java.
The Java and the PHPJava comparison table is 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:** The PHPJava cannot calculate big numbered `double` and `float` values because of `gmp_pow` cannot calculate negative exponents.
So the PHPJava use built-in functions which is `pow`.
## Run unit tests
- PHPUnit test is below.
```
$ ./vendor/bin/phpunit tests
```
- PHP Coding standards testing is below.
```
$ ./vendor/bin/phpcs --standard=phpcs.xml src
```
- All testing is below.
```
$ composer run tests
```
## Reference
- [Java Virtual Machine Specification](https://docs.oracle.com/javase/specs/jvms/se11/html/index.html)
## License
MIT