diff --git a/src/Core/JVM/ActiveAttributes.php b/src/Core/JVM/ActiveAttributes.php deleted file mode 100644 index d13ecba8..00000000 --- a/src/Core/JVM/ActiveAttributes.php +++ /dev/null @@ -1,33 +0,0 @@ -reader = $reader; - for ($i = 0; $i < $entries; $i++) { - // not implemented, read only - $this->entries[$i] = new AttributeInfo($reader); - $this->entries[$i]->setConstantPool($constantPool); - $this->entries[$i]->setDebugTool($debugTool); - $this->entries[$i]->execute(); - } - } - - public function getEntries() - { - return $this->entries; - } -} diff --git a/src/Core/JVM/ActiveInterface.php b/src/Core/JVM/ActiveInterface.php deleted file mode 100644 index 0bd51136..00000000 --- a/src/Core/JVM/ActiveInterface.php +++ /dev/null @@ -1,29 +0,0 @@ -reader = $reader; - for ($i = 0; $i < $entries; $i++) { - $this->entries[$i] = $reader->getBinaryReader()->readUnsignedShort(); - } - } - - public function getEntries() - { - return $this->entries; - } -} diff --git a/src/Core/JVM/AttributePool.php b/src/Core/JVM/AttributePool.php new file mode 100644 index 00000000..475aee11 --- /dev/null +++ b/src/Core/JVM/AttributePool.php @@ -0,0 +1,61 @@ +reader = $reader; + for ($i = 0; $i < $entries; $i++) { + // not implemented, read only + $entry = (new AttributeInfo($reader)) + ->setConstantPool($constantPool) + ->setDebugTool($debugTool); + $entry->execute(); + + $this->entries[] = $entry; + } + } + + public function getEntries() + { + return $this->entries; + } + + public function offsetExists($offset) + { + return isset($this->entries[$offset]); + } + + public function offsetGet($offset) + { + return $this->entries[$offset]; + } + + public function count() + { + return count($this->entries); + } + + public function offsetSet($offset, $value) + { + throw new ReadOnlyException('You cannot rewrite datum. The Attribute Pool is read-only.'); + } + + public function offsetUnset($offset) + { + throw new ReadOnlyException('You cannot rewrite datum. The Attribute Pool is read-only.'); + } +} diff --git a/src/Core/JVM/ConstantPool.php b/src/Core/JVM/ConstantPool.php index fdf4d0a9..62fa6478 100644 --- a/src/Core/JVM/ConstantPool.php +++ b/src/Core/JVM/ConstantPool.php @@ -20,7 +20,7 @@ use PHPJava\Kernel\Structures\_Utf8; use PHPJava\Kernel\Structures\StructureInterface; -class ConstantPool implements \ArrayAccess +class ConstantPool implements \ArrayAccess, \Countable { private $entries = []; private $reader; @@ -102,6 +102,11 @@ public function offsetGet($offset) return $this->entries[$offset]; } + public function count() + { + return count($this->entries); + } + public function offsetSet($offset, $value) { throw new ReadOnlyException('You cannot rewrite datum. The Constant Pool is read-only.'); diff --git a/src/Core/JVM/ActiveFields.php b/src/Core/JVM/FieldPool.php similarity index 54% rename from src/Core/JVM/ActiveFields.php rename to src/Core/JVM/FieldPool.php index 0d1d0d34..7d09a121 100644 --- a/src/Core/JVM/ActiveFields.php +++ b/src/Core/JVM/FieldPool.php @@ -3,10 +3,11 @@ use PHPJava\Core\JavaClass; use PHPJava\Core\Stream\Reader\ReaderInterface; +use PHPJava\Exceptions\ReadOnlyException; use PHPJava\Kernel\Structures\_FieldInfo; use PHPJava\Utilities\DebugTool; -class ActiveFields +class FieldPool implements \ArrayAccess, \Countable { private $entries = []; private $reader; @@ -30,4 +31,29 @@ public function getEntries() { return $this->entries; } + + public function offsetExists($offset) + { + return isset($this->entries[$offset]); + } + + public function offsetGet($offset) + { + return $this->entries[$offset]; + } + + public function count() + { + return count($this->entries); + } + + public function offsetSet($offset, $value) + { + throw new ReadOnlyException('You cannot rewrite datum. The Field Pool is read-only.'); + } + + public function offsetUnset($offset) + { + throw new ReadOnlyException('You cannot rewrite datum. The Field Pool is read-only.'); + } } diff --git a/src/Core/JVM/InterfacePool.php b/src/Core/JVM/InterfacePool.php new file mode 100644 index 00000000..87757024 --- /dev/null +++ b/src/Core/JVM/InterfacePool.php @@ -0,0 +1,55 @@ +reader = $reader; + for ($i = 0; $i < $entries; $i++) { + $this->entries[$i] = $reader->getBinaryReader()->readUnsignedShort(); + } + } + + public function getEntries() + { + return $this->entries; + } + + public function offsetExists($offset) + { + return isset($this->entries[$offset]); + } + + public function offsetGet($offset) + { + return $this->entries[$offset]; + } + + public function count() + { + return count($this->entries); + } + + public function offsetSet($offset, $value) + { + throw new ReadOnlyException('You cannot rewrite datum. The Interface Pool is read-only.'); + } + + public function offsetUnset($offset) + { + throw new ReadOnlyException('You cannot rewrite datum. The Interface Pool is read-only.'); + } +} diff --git a/src/Core/JVM/Invoker/Invokable.php b/src/Core/JVM/Invoker/Invokable.php index f3b8177f..4c8d91cd 100644 --- a/src/Core/JVM/Invoker/Invokable.php +++ b/src/Core/JVM/Invoker/Invokable.php @@ -56,13 +56,10 @@ public function __construct(JavaClassInvoker $javaClassInvoker, array $methods, * @param mixed ...$arguments * @return null * @throws IllegalJavaClassException - * @throws NoSuchMethodException * @throws RuntimeException - * @throws UndefinedMethodException * @throws UndefinedOpCodeException * @throws \PHPJava\Exceptions\TypeException * @throws \PHPJava\Exceptions\UnableToFindAttributionException - * @throws \ReflectionException */ public function call(string $name, ...$arguments) { diff --git a/src/Core/JVM/ActiveMethods.php b/src/Core/JVM/MethodPool.php similarity index 53% rename from src/Core/JVM/ActiveMethods.php rename to src/Core/JVM/MethodPool.php index fdedebb7..790ae25d 100644 --- a/src/Core/JVM/ActiveMethods.php +++ b/src/Core/JVM/MethodPool.php @@ -2,10 +2,11 @@ namespace PHPJava\Core\JVM; use PHPJava\Core\Stream\Reader\ReaderInterface; +use PHPJava\Exceptions\ReadOnlyException; use PHPJava\Kernel\Structures\_MethodInfo; use PHPJava\Utilities\DebugTool; -class ActiveMethods +class MethodPool implements \ArrayAccess, \Countable { private $entries = []; private $reader; @@ -29,4 +30,29 @@ public function getEntries() { return $this->entries; } + + public function offsetExists($offset) + { + return isset($this->entries[$offset]); + } + + public function offsetGet($offset) + { + return $this->entries[$offset]; + } + + public function count() + { + return count($this->entries); + } + + public function offsetSet($offset, $value) + { + throw new ReadOnlyException('You cannot rewrite datum. The Interface Pool is read-only.'); + } + + public function offsetUnset($offset) + { + throw new ReadOnlyException('You cannot rewrite datum. The Interface Pool is read-only.'); + } } diff --git a/src/Core/JVM/Parameters/Runtime.php b/src/Core/JVM/Parameters/Runtime.php index a5f61fac..e5be9951 100644 --- a/src/Core/JVM/Parameters/Runtime.php +++ b/src/Core/JVM/Parameters/Runtime.php @@ -21,6 +21,12 @@ final class Runtime const LOG_PATH = 'php://stderr'; const LOG_LEVEL = Logger::EMERGENCY; + const LOAD_ATTRIBUTES = [ + 'Code', + 'Exceptions', + 'SourceFile', + ]; + const PHP_PACKAGES_MAPS = [ 'String' => '_String', 'Object' => '_Object', diff --git a/src/Core/JVM/Stream/BinaryReader.php b/src/Core/JVM/Stream/BinaryReader.php index 4f668e4e..ed909c22 100644 --- a/src/Core/JVM/Stream/BinaryReader.php +++ b/src/Core/JVM/Stream/BinaryReader.php @@ -35,17 +35,17 @@ public function readByte() public function readUnsignedByte() { - return (int) sprintf('%u', ord($this->read(1))); + return current(unpack('C', $this->read(1))); } public function readUnsignedInt() { - return base_convert(bin2hex($this->read(4)), 16, 10); + return current(unpack('N', $this->read(4))); } public function readUnsignedShort() { - return (int) sprintf('%u', hexdec(bin2hex($this->read(2)))); + return current(unpack('n', $this->read(2))); } public function readInt() @@ -57,16 +57,12 @@ public function readInt() public function readShort() { $short = $this->readUnsignedShort(); - return (($short & 0x8000) > 0) ? ($short - 0xFFFF - 1) : $short ; + return (($short & 0x8000) > 0) ? ($short - 0xFFFF - 1) : $short; } public function readUnsignedLong() { - if (PHP_INT_MAX === 2147483647) { - return base_convert(bin2hex($this->read(8)), 16, 10); - } - - return (int) sprintf('%u', hexdec(bin2hex($this->read(8)))); + return current(unpack('J', $this->read(8))); } public function readLong() diff --git a/src/Core/JavaClass.php b/src/Core/JavaClass.php index 93d46272..cc8f6ab0 100644 --- a/src/Core/JavaClass.php +++ b/src/Core/JavaClass.php @@ -1,10 +1,10 @@ activeInterfaces = new ActiveInterface( + $this->interfacePool = new InterfacePool( $reader, $reader->getBinaryReader()->readUnsignedShort(), $this->constantPool, $this->debugTool ); - $this->debugTool->getLogger()->info('Extracted interfaces: ' . count($this->activeInterfaces->getEntries())); + $this->debugTool->getLogger()->info('Extracted interfaces: ' . count($this->interfacePool)); // read fields - $this->activeFields = new ActiveFields( + $this->fieldPool = new FieldPool( $reader, $reader->getBinaryReader()->readUnsignedShort(), $this->constantPool, $this->debugTool ); - $this->debugTool->getLogger()->info('Extracted fields: ' . count($this->activeFields->getEntries())); + $this->debugTool->getLogger()->info('Extracted fields: ' . count($this->fieldPool)); // read methods - $this->activeMethods = new ActiveMethods( + $this->methodPool = new MethodPool( $reader, $reader->getBinaryReader()->readUnsignedShort(), $this->constantPool, $this->debugTool ); - $this->debugTool->getLogger()->info('Extracted methods: ' . count($this->activeMethods->getEntries())); + $this->debugTool->getLogger()->info('Extracted methods: ' . count($this->methodPool)); // read Attributes - $this->activeAttributes = new ActiveAttributes( + $this->attributePool = new AttributePool( $reader, $reader->getBinaryReader()->readUnsignedShort(), $this->constantPool, $this->debugTool ); - $this->debugTool->getLogger()->info('Extracted attributes: ' . count($this->activeAttributes->getEntries())); + $this->debugTool->getLogger()->info('Extracted attributes: ' . count($this->attributePool)); - foreach ($this->activeAttributes->getEntries() as $entry) { + foreach ($this->attributePool as $entry) { if ($entry->getAttributeData() instanceof InnerClassesAttribute) { $this->innerClasses = array_merge( $this->innerClasses, @@ -261,14 +260,14 @@ public function getInnerClasses(): array return $this->innerClasses; } - public function getFields(): array + public function getDefinedFields(): array { - return $this->activeFields->getEntries(); + return $this->fieldPool->getEntries(); } - public function getMethods(): array + public function getDefinedMethods(): array { - return $this->activeMethods->getEntries(); + return $this->methodPool->getEntries(); } public function getInvoker(): JavaClassInvoker diff --git a/src/Core/JavaClassInvoker.php b/src/Core/JavaClassInvoker.php index 73cacecd..8db62805 100644 --- a/src/Core/JavaClassInvoker.php +++ b/src/Core/JavaClassInvoker.php @@ -55,7 +55,7 @@ public function __construct(JavaClass $javaClass, array $options) $this->options = $options; $cpInfo = $javaClass->getConstantPool(); - foreach ($javaClass->getMethods() as $methodInfo) { + foreach ($javaClass->getDefinedMethods() as $methodInfo) { /** * @var _MethodInfo $methodInfo */ @@ -68,7 +68,7 @@ public function __construct(JavaClass $javaClass, array $options) } } - foreach ($javaClass->getFields() as $fieldInfo) { + foreach ($javaClass->getDefinedFields() as $fieldInfo) { /** * @var _FieldInfo $fieldInfo */ diff --git a/src/Kernel/Attributes/AttributeInfo.php b/src/Kernel/Attributes/AttributeInfo.php index 84313d7e..d28040e7 100644 --- a/src/Kernel/Attributes/AttributeInfo.php +++ b/src/Kernel/Attributes/AttributeInfo.php @@ -1,6 +1,8 @@ attributeNameIndex = $this->readUnsignedShort(); $this->attributeLength = $this->readUnsignedInt(); $cpInfo = $this->getConstantPool(); $currentOffset = $this->getOffset(); $attributeName = $cpInfo[$this->attributeNameIndex]->getString(); + + if ($loadAttributes !== null && !in_array($attributeName, $loadAttributes, true)) { + $this->read($this->attributeLength); + $this->getDebugTool()->getLogger()->debug('Skip to load an attribute: ' . $attributeName); + return; + } + $classAttributeName = '\\PHPJava\\Kernel\\Attributes\\' . $attributeName . 'Attribute'; $this->getDebugTool()->getLogger()->debug('Load an attribute: ' . $attributeName); $this->attributeData = new $classAttributeName($this->reader); diff --git a/src/Kernel/Attributes/CodeAttribute.php b/src/Kernel/Attributes/CodeAttribute.php index 98b618bb..6436fa3b 100644 --- a/src/Kernel/Attributes/CodeAttribute.php +++ b/src/Kernel/Attributes/CodeAttribute.php @@ -40,11 +40,7 @@ public function execute(): void $exceptionTable = new \PHPJava\Kernel\Structures\_ExceptionTable($this->reader); $exceptionTable->setConstantPool($this->getConstantPool()); $exceptionTable->setDebugTool($this->getDebugTool()); - $exceptionTable->setStartPc($this->readUnsignedShort()) - ->setEndPc($this->readUnsignedShort()) - ->setHandlerPc($this->readUnsignedShort()) - ->setCatchType($this->readUnsignedShort()) - ->execute(); + $exceptionTable->execute(); $this->exceptionTables[] = $exceptionTable; } diff --git a/src/Kernel/Attributes/LineNumberTableAttribute.php b/src/Kernel/Attributes/LineNumberTableAttribute.php index c0fe5bff..f1e70c8f 100644 --- a/src/Kernel/Attributes/LineNumberTableAttribute.php +++ b/src/Kernel/Attributes/LineNumberTableAttribute.php @@ -20,9 +20,7 @@ public function execute(): void $lineNumberTable = new \PHPJava\Kernel\Structures\_LineNumberTable($this->reader); $lineNumberTable->setConstantPool($this->getConstantPool()); $lineNumberTable->setDebugTool($this->getDebugTool()); - $lineNumberTable->setStartPc($this->readUnsignedShort()) - ->setLineNumber($this->readUnsignedShort()) - ->execute(); + $lineNumberTable->execute(); $this->lineNumberTables[] = $lineNumberTable; } } diff --git a/src/Kernel/Mnemonics/_getstatic.php b/src/Kernel/Mnemonics/_getstatic.php index 7ee9bee7..56b21a69 100644 --- a/src/Kernel/Mnemonics/_getstatic.php +++ b/src/Kernel/Mnemonics/_getstatic.php @@ -21,7 +21,7 @@ public function execute(): void $signature = Formatter::parseSignature($cpInfo[$cpInfo[$cp->getNameAndTypeIndex()]->getDescriptorIndex()]->getString()); if ($cp instanceof _Fieldref) { - foreach ($this->javaClass->getFields() as $field) { + foreach ($this->javaClass->getDefinedFields() as $field) { if ($cpInfo[$field->getNameIndex()]->getString() === $cpInfo[$cpInfo[$cp->getNameAndTypeIndex()]->getNameIndex()]->getString()) { // push stack $fieldName = $cpInfo[$field->getNameIndex()]->getString(); diff --git a/src/Kernel/Mnemonics/_invokestatic.php b/src/Kernel/Mnemonics/_invokestatic.php index c6af99fd..0de99677 100644 --- a/src/Kernel/Mnemonics/_invokestatic.php +++ b/src/Kernel/Mnemonics/_invokestatic.php @@ -25,8 +25,6 @@ public function execute(): void $methodName = $cpInfo[$cpInfo[$cp->getNameAndTypeIndex()]->getNameIndex()]->getString(); $signature = Formatter::parseSignature($cpInfo[$cpInfo[$cp->getNameAndTypeIndex()]->getDescriptorIndex()]->getString()); - $this->getOptions('class_resolver') - ->resolve($cpInfo[$cpInfo[$cp->getClassIndex()]->getClassIndex()]->getString()); [$resourceType, $classObject] = $this->getOptions('class_resolver') ->resolve($cpInfo[$cpInfo[$cp->getClassIndex()]->getClassIndex()]->getString()); diff --git a/src/Kernel/Structures/_ExceptionTable.php b/src/Kernel/Structures/_ExceptionTable.php index 669a6848..3191308d 100644 --- a/src/Kernel/Structures/_ExceptionTable.php +++ b/src/Kernel/Structures/_ExceptionTable.php @@ -17,30 +17,10 @@ class _ExceptionTable implements StructureInterface public function execute(): void { - } - - public function setStartPc($startPc) - { - $this->startPc = $startPc; - return $this; - } - - public function setEndPc($endPc) - { - $this->endPc = $endPc; - return $this; - } - - public function setHandlerPc($handlerPc) - { - $this->handlerPc = $handlerPc; - return $this; - } - - public function setCatchType($catchType) - { - $this->catchType = $catchType; - return $this; + $this->startPc = $this->readUnsignedShort(); + $this->endPc = $this->readUnsignedShort(); + $this->handlerPc = $this->readUnsignedShort(); + $this->catchType = $this->readUnsignedShort(); } public function getStartPc() diff --git a/src/Kernel/Structures/_LineNumberTable.php b/src/Kernel/Structures/_LineNumberTable.php index 9f46b105..27b300a5 100644 --- a/src/Kernel/Structures/_LineNumberTable.php +++ b/src/Kernel/Structures/_LineNumberTable.php @@ -15,22 +15,15 @@ class _LineNumberTable implements StructureInterface public function execute(): void { + $this->startPc = $this->readUnsignedShort(); + $this->lineNumber = $this->readUnsignedShort(); } - public function setStartPc($startPc) - { - $this->startPc = $startPc; - return $this; - } - public function setLineNumber($lineNumber) - { - $this->lineNumber = $lineNumber; - return $this; - } public function getStartPc() { return $this->startPc; } + public function getLineNumber() { return $this->lineNumber;