Skip to content

Commit 29afddc

Browse files
committed
Merge branch 'master' of github.com:memory-agape/php-java
2 parents 0e16f57 + 3f9993f commit 29afddc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+897
-86
lines changed

README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,80 @@ $dynamicMethodAccessor
223223
echo $result;
224224
```
225225

226+
### Call ambiguous method into Java from PHP
227+
- PHP types are ambiguous than Java.
228+
- You may want to call a methods in PHP that contain long type in Java.
229+
In its case, you can call a method as follows:
230+
231+
#### ex. ) [Recommended] Wrap with `\PHPJava\Kernel\Types\_Long`.
232+
##### In Java
233+
```java
234+
class Test
235+
{
236+
public static void includingLongTypeParameter(long n)
237+
{
238+
System.out.println(n);
239+
}
240+
241+
}
242+
```
243+
244+
##### In PHP
245+
```php
246+
<?php
247+
$javaClass->getInvoker()->getStatic()->getMethods()->call(
248+
'includingLongTypeParameter',
249+
new \PHPJava\Kernel\Types\_Long(1234)
250+
);
251+
```
252+
253+
The example will return `1234`.
254+
255+
256+
#### ex. ) Set `false` to strict mode within options.
257+
##### In PHP
258+
```php
259+
<?php
260+
use PHPJava\Core\JavaClass;
261+
use PHPJava\Core\JavaClassFileReader;
262+
263+
$javaClass = new JavaClass(
264+
new JavaClassFileReader('Test'),
265+
[
266+
'strict' => false,
267+
]
268+
);
269+
```
270+
271+
### Runtime options
272+
- Available options on `JavaClass` or `JavaArchive` is below:
273+
274+
|Options | Value | Default | Description |Targeted |
275+
|:-------------:|:-------------:|:-------------:|:-------------:|:-------------:|
276+
| entrypoint | ?string | null | Specify to run entrypoint in JAR. | JavaArchive |
277+
| max_stack_exceeded | integer | 9999 | Execute more than the specified number of times be stopped the operation. | JavaClass |
278+
| strict | boolean | true | If strict mode is `true` then execute method, variables and so on with strict. But if strict mode is `false` then execute ambiguously method, variable and etc in PHPJava. | Both |
279+
| validation.method.arguments_count_only | boolean | false | If this mode `true` then ClassResolver validate arguments size only. | JavaClass |
280+
281+
- For example:
282+
```php
283+
<?php
284+
use PHPJava\Core\JavaClass;
285+
use PHPJava\Core\JavaClassFileReader;
286+
287+
$javaClass = new JavaClass(
288+
new JavaClassFileReader('Test'),
289+
[
290+
'max_stack_exceeded' => 12345,
291+
'validation' => [
292+
'method' => [
293+
'arguments_count_only' => true,
294+
],
295+
],
296+
]
297+
);
298+
```
299+
226300
### Output PHPJava operations
227301

228302
- Output debug trace as follows if you want to show operation log:

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "JVM emulator by PHP",
44
"type": "library",
55
"license": "MIT",
6-
"version": "0.0.4.5-dev",
6+
"version": "0.0.5.0-dev",
77
"authors": [
88
{
99
"name": "memory"

src/Core/JVM/DynamicAccessor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ class DynamicAccessor implements AccessorInterface
1919
*/
2020
private $methodAccessor;
2121

22-
public function __construct(JavaClassInvoker $invoker, array $methods)
22+
public function __construct(JavaClassInvoker $invoker, array $methods, array $options = [])
2323
{
24-
$this->methodAccessor = new DynamicMethodInvoker($invoker, $methods);
24+
$this->methodAccessor = new DynamicMethodInvoker($invoker, $methods, $options);
2525
$this->fieldAccessor = new DynamicField($invoker, []);
2626
}
2727

src/Core/JVM/Invoker/Invokable.php

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,19 @@
2121
use PHPJava\Utilities\Formatter;
2222
use PHPJava\Utilities\SuperClassResolver;
2323
use PHPJava\Utilities\TypeResolver;
24+
use PHPJava\Core\JVM\Parameters\Runtime;
2425

2526
trait Invokable
2627
{
2728
private $javaClassInvoker;
2829
private $methods = [];
30+
private $options = [];
2931

30-
public function __construct(JavaClassInvoker $javaClassInvoker, array $methods)
32+
public function __construct(JavaClassInvoker $javaClassInvoker, array $methods, array $options = [])
3133
{
3234
$this->javaClassInvoker = $javaClassInvoker;
3335
$this->methods = $methods;
36+
$this->options = $options;
3437
}
3538

3639
/**
@@ -104,15 +107,36 @@ function ($argument) {
104107
break;
105108
}
106109
$constantPool = ($currentConstantPool = $methodReference->getConstantPool())->getEntries();
110+
$formattedArguments = Formatter::parseSignature(
111+
$constantPool[$methodReference->getDescriptorIndex()]->getString()
112+
)['arguments'];
113+
114+
// does not strict mode can be PHP types
115+
if (!($this->options['strict'] ?? Runtime::STRICT)) {
116+
$formattedArguments = Formatter::signatureConvertToAmbiguousForPHP($formattedArguments);
117+
}
118+
107119
/**
108120
* @var _MethodInfo $methodReference
109121
*/
110-
$methodSignature = Formatter::buildArgumentsSignature(
111-
Formatter::parseSignature($constantPool[$methodReference->getDescriptorIndex()]->getString())['arguments']
112-
);
113-
if ($methodSignature === $convertedPassedArguments) {
114-
$method = $methodReference;
115-
break;
122+
$methodSignature = Formatter::buildArgumentsSignature($formattedArguments);
123+
124+
if (!($this->options['validation']['method']['arguments_count_only'] ?? Runtime::VALIDATION_METHOD_ARGUMENTS_COUNT_ONLY)) {
125+
if ($methodSignature === $convertedPassedArguments) {
126+
$method = $methodReference;
127+
break;
128+
}
129+
}
130+
if (($this->options['validation']['method']['arguments_count_only'] ?? Runtime::VALIDATION_METHOD_ARGUMENTS_COUNT_ONLY) === true) {
131+
$size = count($formattedArguments);
132+
$passedArgumentsSize = count(
133+
$arguments
134+
);
135+
136+
if ($size === $passedArgumentsSize) {
137+
$method = $methodReference;
138+
break;
139+
}
116140
}
117141
}
118142

@@ -157,8 +181,11 @@ function ($argument) {
157181
$mnemonicMap = new OpCode();
158182
$executedCounter = 0;
159183
while ($reader->getOffset() < $codeAttribute->getOpCodeLength()) {
160-
if (++$executedCounter > \PHPJava\Core\JVM\Parameters\Invoker::MAX_STACK_EXCEEDED) {
161-
throw new RuntimeException('Max stack exceeded. PHPJava has been stopped by safety guard. Maybe Java class has illegal program counter, stacks, or OpCode.');
184+
if (++$executedCounter > ($this->options['max_stack_exceeded'] ?? Runtime::MAX_STACK_EXCEEDED)) {
185+
throw new RuntimeException(
186+
'Max stack exceeded. PHPJava has been stopped by safety guard.' .
187+
' Maybe Java class has illegal program counter, stacks, or OpCode.'
188+
);
162189
}
163190
$opcode = $reader->readUnsignedByte();
164191
$mnemonic = $mnemonicMap->getName($opcode);

src/Core/JVM/Parameters/Invoker.php

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
namespace PHPJava\Core\JVM\Parameters;
3+
4+
final class Runtime
5+
{
6+
const ENTRYPOINT = null;
7+
8+
const MAX_STACK_EXCEEDED = 9999;
9+
const STRICT = true;
10+
11+
const VALIDATION_METHOD_ARGUMENTS_COUNT_ONLY = false;
12+
}

src/Core/JVM/StaticAccessor.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ class StaticAccessor implements AccessorInterface
1919
*/
2020
private $methodAccessor;
2121

22-
public function __construct(JavaClassInvoker $invoker, array $methods)
22+
public function __construct(JavaClassInvoker $invoker, array $methods, array $options = [])
2323
{
24-
$this->methodAccessor = new StaticMethodInvoker($invoker, $methods);
24+
$this->methodAccessor = new StaticMethodInvoker($invoker, $methods, $options);
2525
$this->fieldAccessor = new StaticField($invoker, []);
2626
}
2727

src/Core/JavaArchive.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22
namespace PHPJava\Core;
33

4+
use PHPJava\Core\JVM\Parameters\Runtime;
45
use PHPJava\Exceptions\UndefinedEntrypointException;
56
use PHPJava\Imitation\java\io\FileNotFoundException;
67
use PHPJava\Imitation\java\lang\ClassNotFoundException;
@@ -17,21 +18,25 @@ class JavaArchive
1718
private $expandedHArchive;
1819
private $files = [];
1920
private $classes = [];
21+
private $options = [];
2022

2123
/**
2224
* @param string $jarFile
23-
* @param string|null $entryPoint
25+
* @param array $options
2426
* @throws FileNotFoundException
2527
* @throws \PHPJava\Exceptions\ReadEntryException
2628
* @throws \PHPJava\Exceptions\ValidatorException
2729
* @throws \PHPJava\Imitation\java\lang\ClassNotFoundException
2830
*/
29-
public function __construct(string $jarFile, string $entryPoint = null)
31+
public function __construct(string $jarFile, array $options = [])
3032
{
3133
$this->jarFile = $jarFile;
3234
$archive = new \ZipArchive();
3335
$archive->open($jarFile);
3436
$this->expandedHArchive = $archive;
37+
$this->options = $options;
38+
39+
$this->manifestData['main-class'] = $options['entrypoint'] ?? Runtime::ENTRYPOINT;
3540

3641
// Add resolving path
3742
ClassResolver::add(
@@ -72,10 +77,13 @@ function ($fileName) {
7277
);
7378

7479
foreach ($this->files as $className => $code) {
75-
$this->classes[str_replace('/', '.', $className)] = new JavaClass(new JavaClassInlineReader(
76-
$className,
77-
$code
78-
));
80+
$this->classes[str_replace('/', '.', $className)] = new JavaClass(
81+
new JavaClassInlineReader(
82+
$className,
83+
$code
84+
),
85+
$this->options
86+
);
7987
}
8088

8189
$currentDirectory = getcwd();

src/Core/JavaClass.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,17 @@ class JavaClass
7171

7272
private $superClass;
7373

74+
private $options = [];
75+
7476
/**
7577
* JavaClass constructor.
7678
* @param JavaClassReaderInterface $reader
79+
* @param array $options
7780
* @throws ValidatorException
7881
* @throws \PHPJava\Exceptions\ReadEntryException
7982
* @throws \PHPJava\Imitation\java\lang\ClassNotFoundException
8083
*/
81-
public function __construct(JavaClassReaderInterface $reader)
84+
public function __construct(JavaClassReaderInterface $reader, array $options = [])
8285
{
8386
// Validate Java file
8487
if (!(new MagicByte($reader->getBinaryReader()->readUnsignedInt()))->isValid()) {
@@ -162,7 +165,10 @@ public function __construct(JavaClassReaderInterface $reader)
162165
}
163166
}
164167

165-
$this->invoker = new JavaClassInvoker($this);
168+
$this->invoker = new JavaClassInvoker(
169+
$this,
170+
$options
171+
);
166172
}
167173

168174
public function __debugInfo()

src/Core/JavaClassInvoker.php

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,16 @@ class JavaClassInvoker
4141

4242
private $specialInvoked = [];
4343

44+
private $options = [];
45+
4446
/**
45-
* JavaClassInvoker constructor.
4647
* @param JavaClass $javaClass
48+
* @param array $options
4749
*/
48-
public function __construct(JavaClass $javaClass)
50+
public function __construct(JavaClass $javaClass, array $options)
4951
{
5052
$this->javaClass = $javaClass;
53+
$this->options = $options;
5154
$cpInfo = $javaClass->getConstantPool()->getEntries();
5255

5356
foreach ($javaClass->getMethods() as $methodInfo) {
@@ -78,12 +81,14 @@ public function __construct(JavaClass $javaClass)
7881

7982
$this->dynamicAccessor = new DynamicAccessor(
8083
$this,
81-
$this->dynamicMethods
84+
$this->dynamicMethods,
85+
$this->options
8286
);
8387

8488
$this->staticAccessor = new StaticAccessor(
8589
$this,
86-
$this->staticMethods
90+
$this->staticMethods,
91+
$this->options
8792
);
8893

8994
// call <clinit>
@@ -100,7 +105,8 @@ public function construct(...$arguments): self
100105
{
101106
$this->dynamicAccessor = new DynamicAccessor(
102107
$this,
103-
$this->dynamicMethods
108+
$this->dynamicMethods,
109+
$this->options
104110
);
105111

106112
if (isset($this->dynamicMethods['<init>'])) {

0 commit comments

Comments
 (0)