diff --git a/ApplicationDeveloperGuide/debuggerProxy.rst b/ApplicationDeveloperGuide/debuggerProxy.rst index fe9bb9c70..f9f625fdf 100644 --- a/ApplicationDeveloperGuide/debuggerProxy.rst +++ b/ApplicationDeveloperGuide/debuggerProxy.rst @@ -142,68 +142,72 @@ A script file named ``vee-memory-dump.mac`` (for IAR) or ``vee-memory-dump.gdb`` You can now use this script to dump the memory of the running Executable. +.. _dump_vee_memory: + Dump the memory of the running Executable ----------------------------------------- -With IAR Debugger -~~~~~~~~~~~~~~~~~ -.. note:: - You must use a version of IAR Workbench for which the ``vee-memory-dump.mac`` script file is generated. +.. tabs:: - A script file generated for IAR8 will not work on IAR Workbench 9.x.x and vice versa. - -In IAR Embedded Workbench: + .. tab:: IAR Debugger -- Register the generated ``vee-memory-dump.mac`` script file in the debugger project option: - - #. Open the Debugger Project option window by clicking on ``Project > Options... > Debugger > Setup`` - #. Check the option ``Use macro file(s)`` and browse to the generated ``vee-memory-dump.mac`` file. - #. Click on ``OK`` to confirm. - - .. figure:: images/iar-cspy1.png - :alt: IAR Embedded Workbench Debugger Project Option - :align: center + .. note:: + You must use a version of IAR Workbench for which the ``vee-memory-dump.mac`` script file is generated. - IAR Debugger Project Option + A script file generated for IAR8 will not work on IAR Workbench 9.x.x and vice versa. -- Add the macro ``dumpMemories()`` as an action expression to a code breakpoint: + In IAR Embedded Workbench: - #. Open IAR Breakpoints window by clicking on ``View > Breakpoints`` - #. Right click on IAR Breakpoints window and select ``New Breakpoint > Code`` - #. In the ``Expression`` text field, enter ``dumpMemories()`` and click on ``OK`` + - Register the generated ``vee-memory-dump.mac`` script file in the debugger project option: - .. figure:: images/iar-cspy2.png - :alt: IAR Breakpoint editor - :align: center + #. Open the Debugger Project option window by clicking on ``Project > Options... > Debugger > Setup`` + #. Check the option ``Use macro file(s)`` and browse to the generated ``vee-memory-dump.mac`` file. + #. Click on ``OK`` to confirm. - IAR Breakpoint editor + .. figure:: images/iar-cspy1.png + :alt: IAR Embedded Workbench Debugger Project Option + :align: center -When the IAR Debugger hits the specified breakpoint, the ``dumpMemories()`` macro function is executed and the memory is dumped into ``*.hex`` files. + IAR Debugger Project Option -The ``*.hex`` files are generated in the same directory as the ``vee-memory-dump.mac`` file. + - Add the macro ``dumpMemories()`` as an action expression to a code breakpoint: -With GNU Debugger (GDB) -~~~~~~~~~~~~~~~~~~~~~~~ + #. Open IAR Breakpoints window by clicking on ``View > Breakpoints`` + #. Right click on IAR Breakpoints window and select ``New Breakpoint > Code`` + #. In the ``Expression`` text field, enter ``dumpMemories()`` and click on ``OK`` -In your GDB console: + .. figure:: images/iar-cspy2.png + :alt: IAR Breakpoint editor + :align: center -- Create a breakpoint at a specific safe point (Core Engine hooks or native function) + IAR Breakpoint editor -.. code-block:: sh + When the IAR Debugger hits the specified breakpoint, the ``dumpMemories()`` macro function is executed and the memory is dumped into ``*.hex`` files. - # E.g. Add breakpoint at LLMJVM_on_Runtime_gc_done hook - break LLMJVM_on_Runtime_gc_done - run + The ``*.hex`` files are generated in the same directory as the ``vee-memory-dump.mac`` file. -- When the running Executable stops at the Breakpoint, run the ``vee-memory-dump.gdb`` script file to dump the memory. + .. tab:: GNU Debugger (GDB) -.. code-block:: sh + In your GDB console: + + - Create a breakpoint at a specific safe point (Core Engine hooks or native function) + + .. code-block:: sh + + # E.g. Add breakpoint at LLMJVM_on_Runtime_gc_done hook + break LLMJVM_on_Runtime_gc_done + run + + - When the running Executable stops at the Breakpoint, run the ``vee-memory-dump.gdb`` script file to dump the memory. + + .. code-block:: sh + + # E.g. Run the GDB memory dump script + source [/path/to]/vee-memory-dump.gdb - # E.g. Run the GDB memory dump script - source [/path/to]/vee-memory-dump.gdb + The memory is dumped into ``*.hex`` files in the same directory as the ``vee-memory-dump.gdb`` file. -The memory is dumped into ``*.hex`` files in the same directory as the ``vee-memory-dump.gdb`` file. Start the VEE Debugger Proxy ---------------------------- diff --git a/ApplicationDeveloperGuide/sectionArchitectureOptions.rst b/ApplicationDeveloperGuide/sectionArchitectureOptions.rst index a95c2a3bb..e4208467d 100644 --- a/ApplicationDeveloperGuide/sectionArchitectureOptions.rst +++ b/ApplicationDeveloperGuide/sectionArchitectureOptions.rst @@ -127,6 +127,8 @@ Specifies the Managed Heap size in bytes. A Managed Heap contains live objects. An OutOfMemory error can occur if the heap is too small. +.. note:: The Managed heap can also be allocated (and sized) dynamically (see :ref:`dynamic_heap_config`), in which case this option is ignored. + .. _option_immortal_heap: Option(text): Immortals Heap size (in bytes) @@ -140,9 +142,11 @@ Option(text): Immortals Heap size (in bytes) Specifies the Immortals Heap size in bytes. -The Immortals Heap contains allocated Immortal objects. An OutOfMemory error can +The Immortals Heap contains the allocated Immortal objects. An OutOfMemory error can occur if the heap is too small. +.. note:: The Immortals heap can also be allocated (and sized) dynamically (see :ref:`dynamic_heap_config`), in which case this option is ignored. + Group: Threads ^^^^^^^^^^^^^^ diff --git a/SDK6UserGuide/heapAnalyzer.rst b/SDK6UserGuide/heapAnalyzer.rst index b4723bcfe..bcf090701 100644 --- a/SDK6UserGuide/heapAnalyzer.rst +++ b/SDK6UserGuide/heapAnalyzer.rst @@ -134,8 +134,9 @@ In order to generate a Heap dump of an Application running on a device: Retrieve the ``.hex`` file from the device ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you are in a Mono-Sandbox context, you only have to dump the Core Engine heap section. -Here is an example of GDB commands: +If you are in a Mono-Sandbox context and do not use :ref:`dynamic Heap configuration`: +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +You only have to dump the Core Engine heap section. Here is an example of GDB commands: .. code-block:: console @@ -144,52 +145,37 @@ Here is an example of GDB commands: continue dump ihex memory heap.hex &_java_heap_start &_java_heap_end -You now have the ``.hex`` file and need to extract the Heap dump. -If you are in a Multi-Sandbox context, the following sections must be dumped additionally: +Otherwise, you must: +"""""""""""""""""""" +- generate the :ref:`VEE memory dump script ` which will dump all the required sections. +- :ref:`dump_vee_memory` +- Depending on if you are using a Mono-Sandbox or a Multi-Sandbox : + - In a Mono-Sandbox context and not using :ref:`dynamic Heap configuration`, use ``{N}_java_heap.hex``. + - If you are in a Multi-Sandbox context or using :ref:`dynamic Heap configuration` you have to merge all ``.hex`` files with: -- the installed features table. - - .. code-block:: console - - dump ihex memory &java_features_dynamic_start &java_features_dynamic_end - -- the installed features sections. These are specific to your VEE Port, depending on the `LLKERNEL implementation `. - - .. code-block:: console - - dump ihex memory - - To simplify the dump commands, you can also consider the following options : - - - either dump the entire memory where microej runtime and code sections are linked, - - or generate the :ref:`VEE memory dump script ` which will dump all the required sections instead. - - .. note:: - - In a Mono-Sandbox context, use ``1_java_heap.hex``. + .. tabs:: - In a Multi-Sandbox context, merge (at least) ``1_java_heap.hex`` and ``9_installed_features.hex`` with: + .. tab:: Command Prompt - .. tabs:: + .. code-block:: bat - .. tab:: Command Prompt + copy /b *.hex memory.hex - .. code-block:: bat + .. tab:: PowerShell - copy /b 1_java_heap.hex + 9_installed_features.hex memory.hex + .. code-block:: powershell - .. tab:: PowerShell + Get-ChildItem *.hex | Get-Content -Raw | Set-Content -NoNewline memory.hex - .. code-block:: powershell + .. tab:: Bash - Get-Content 1_java_heap.hex, 9_installed_features.hex | Set-Content memory.hex + .. code-block:: bash - .. tab:: Bash + cat *.hex > memory.hex - .. code-block:: bash - cat 1_java_heap.hex 9_installed_features.hex > memory.hex +You now have a single ``.hex`` file and can continue to the next section. .. _sdk6_heapdumper_extract_heap: @@ -254,7 +240,7 @@ You can find the list of available options below: Heap Viewer ----------- -To open the Heap Viewer tool, select a heap dump XML file in the :guilabel:`Package Explorer`, +To open the Heap Viewer tool (:ref:`Included in MicroEJ Tools`), select a heap dump XML file in the :guilabel:`Package Explorer`, right-click on it and select :guilabel:`Open With` > :guilabel:`Heap Viewer` Alternatively, right-click on it and select :guilabel:`Heap Analyzer` > :guilabel:`Open heap viewer`. diff --git a/SDK6UserGuide/tools.rst b/SDK6UserGuide/tools.rst index 7174dd9fd..fdf9d2793 100644 --- a/SDK6UserGuide/tools.rst +++ b/SDK6UserGuide/tools.rst @@ -31,6 +31,7 @@ The following sections describe the command line tools and their options: stackTraceReader codeCoverageAnalyzer +.. _sdk6_microej_tools: **IDE tools** diff --git a/SDKUserGuide/heapAnalyzer.rst b/SDKUserGuide/heapAnalyzer.rst index e98ca27ea..43f61c44e 100644 --- a/SDKUserGuide/heapAnalyzer.rst +++ b/SDKUserGuide/heapAnalyzer.rst @@ -137,7 +137,7 @@ To generate a Heap dump of an application running on a device: Retrieve the ``.hex`` file from the device ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If you are in a Mono-Sandbox context, you only need to dump the Core Engine heap section. Example GDB commands: +If you are in a Mono-Sandbox context and do not use :ref:`dynamic Heap configuration`, you only need to dump the Core Engine heap section. Example GDB commands: .. code-block:: console @@ -148,24 +148,10 @@ If you are in a Mono-Sandbox context, you only need to dump the Core Engine heap You now have the ``.hex`` file and need to extract the Heap dump. -In a Multi-Sandbox context, additionally dump the following sections: +- Otherwise, dump all MICROEJ VEE heaps. See :ref:`VEE memory dump ` for how to generate a script for your debugger that dumps all required sections. -- Installed features table: - - .. code-block:: console - - dump ihex memory &java_features_dynamic_start &java_features_dynamic_end - -- Installed features sections specific to your VEE Port, depending on the `LLKERNEL implementation `: - - .. code-block:: console - - dump ihex memory - -To simplify the dump commands, consider: +You then have to merge all ``.hex`` files into a single one for the next step. -- Dumping the entire memory where MicroEJ runtime and code sections are linked. -- Generating the :ref:`VEE memory dump script ` to dump all required sections. Convert ``.hex`` dump to ``.heap`` dump ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/VEEPortingGuide/appendix/llapi.rst b/VEEPortingGuide/appendix/llapi.rst index 89362a444..72645c596 100644 --- a/VEEPortingGuide/appendix/llapi.rst +++ b/VEEPortingGuide/appendix/llapi.rst @@ -116,6 +116,16 @@ Set of extra functions that the BSP must implement. .. doxygenfile:: LLBSP_impl.h :sections: define enum innerclass public-attrib func +.. _LLMJVM-API-SECTION-CONF: + +LLMJVM_CONF_impl.h +------------------ + +Set of functions that can be implemented to configure the Core Engine at startup. + +.. doxygenfile:: LLMJVM_CONF_impl.h + :sections: define enum innerclass public-attrib func + .. _LLKF-API-SECTION: diff --git a/VEEPortingGuide/architectureChangelog.rst b/VEEPortingGuide/architectureChangelog.rst index ec675054d..81b1123c7 100644 --- a/VEEPortingGuide/architectureChangelog.rst +++ b/VEEPortingGuide/architectureChangelog.rst @@ -34,6 +34,55 @@ specific configuration: - ``QNX65``: BlackBerry QNX 6.5 - ``QNX70``: BlackBerry QNX 7.0 +.. _changelog-8.5.0: + +[8.5.0] - [unreleased] +---------------------- + +This Architecture version update changes the minimum required Java version to Java 11. + + +Core Engine +~~~~~~~~~~~ + +- Added the ability to dynamically configure the Managed/Immortals Heap memory at Core Engine start time. +- Optimized the Garbage Collector. +- Fixed Math.nextAfter(float start, double direction), returns start if direction is very close to start. +- Fixed Remove direct access to errno in ``microejruntime.a`` + + +Foundation Libraries +~~~~~~~~~~~~~~~~~~~~ + +- Fixed incorrect output of `NaN` when calling `Math.ulp()` with positive `Infinity`. +- Fixed `TimerTask` scheduling issues when using a `Date` with an `ej.bon.Timer` to schedule a task. +- [Multi] - Fixed, calling `Kernel.install(java.io.InputStream)`_ now directly throws `OutOfMemoryError`_ and `StackOverflowError`_ exceptions instead of previously being wrapped in `ej.kf.InvalidFormatException`_. +- [Cortex-M] - Fixed incorrect handling of `NaN` and `Infinity` inputs in `Math.cos()`, `Math.sin()`, `Math.tan()`, `Math.acos()`, and `Math.asin()`, when the underlying C Math library does not process these values properly (the issue was introduced in architecture version 8.4.0). +- [Cortex-M] - Fixed `ByteArray.readXXX()` potentialy returning an incorrect value (the issue was introduced in architecture version `8.3.0`). + +.. _ej.kf.InvalidFormatException: https://repository.microej.com/javadoc/microej_5.x/apis/ej/kf/InvalidFormatException.html +.. _StackOverflowError: https://repository.microej.com/javadoc/microej_5.x/apis/java/lang/StackOverflowError.html + + +Integration +~~~~~~~~~~~ + +- Added the ability to dynamically configure the Managed Heap memory at Core Engine start time. +- Added the ability to dynamically configure the Immortals Heap memory at Core Engine start time. +- Optimized the FSO build time. +- Fixed Memory Map Scripts, which counted the application code in the Core Engine category (the issue was introduced in architecture version `8.4.0`). + +SOAR +~~~~ + +- Fixed a potential crash occurring when using a SDK6 Foundation (present in versions up to SDK 1.3.0). +- Fixed a potential issue where SOAR could report an 'unknown field' error for a field that exists. + +Tools +~~~~~ + +- Fixed in elf util: UpdateSection task used by KF Testsuite to support Portable Independent Executable when ASLR is enabled + .. _changelog-8.4.0: diff --git a/VEEPortingGuide/coreEngine.rst b/VEEPortingGuide/coreEngine.rst index 7864493df..2aa5427e1 100644 --- a/VEEPortingGuide/coreEngine.rst +++ b/VEEPortingGuide/coreEngine.rst @@ -244,6 +244,21 @@ to the Application: .. _java.lang.System.currentTimeMillis(): https://repository.microej.com/javadoc/microej_5.x/apis/java/lang/System.html#currentTimeMillis-- +.. _dynamic_heap_config: + +Configuring Memory Dynamically +------------------------------ + +To configure the heaps sizes at the Core Engine startup time rather than at compile time (see :ref:`Managed Heap size configuration` and :ref:`Immortals Heap size configuration` Application options), +implement the Core Engine configuration Low Level API (see :ref:`LLMJVM_CONF_impl.h`): + +- ``LLMJVM_CONF_impl_get_managed_heap_memory()``: allocates the Managed Heap. +- ``LLMJVM_CONF_impl_get_immortals_heap_memory()``: allocates the Immortals Heap. + +The Core Engine provides a default implementation for those functions which returns memory sections statically allocated using the compile time heaps sizes configuration (& linker script for position). +If the default implementation is overridden, the heap configuration properties are ignored unless the custom implementation uses them. +These functions are called by the Core Engine in ``SNI_createVM()``. + .. _core_engine_error_codes: Error Codes @@ -334,6 +349,17 @@ The following table describes these error codes. | -25 | The function ``LLMJVM_IMPL_shutdown`` defined in the | | | Abstraction Layer implementation returns an error. | +-------------+-------------------------------------------------------------+ + | -26 | The GC mark stack size is too small | + +-------------+-------------------------------------------------------------+ + | -27 | The application object file has not been correctly linked | + | | by the third-party linker. | + +-------------+-------------------------------------------------------------+ + | -28 | The function ``LLMJVM_CONF_impl_get_managed_heap_memory`` | + | | returns an error. | + +-------------+-------------------------------------------------------------+ + | -29 | The function ``LLMJVM_CONF_impl_get_immortals_heap_memory`` | + | | returns an error. | + +-------------+-------------------------------------------------------------+ Example diff --git a/_llapi_doxygen/LLMJVM_CONF/LLMJVM_CONF_impl.h b/_llapi_doxygen/LLMJVM_CONF/LLMJVM_CONF_impl.h new file mode 100644 index 000000000..f0e7b3613 --- /dev/null +++ b/_llapi_doxygen/LLMJVM_CONF/LLMJVM_CONF_impl.h @@ -0,0 +1,95 @@ +/* + * C + * + * Copyright 2025 MicroEJ Corp. All rights reserved. + * This library is provided in source code for use, modification and test, subject to license terms. + * Any modification of the source code will break MicroEJ Corp. warranties on the whole library. + */ + +#ifndef LLMJVM_CONF_IMPL_H +#define LLMJVM_CONF_IMPL_H +#endif + +/** + * @file + * @brief VM configuration low level API + * @author MicroEJ Developer Team + * @version 1.0.0 + * @date 05 aout 2025 + */ + +#ifdef __cplusplus + extern "C" { +#endif + +/** + * @brief Optional user-implemented callback to provide a memory region for the Managed Heap. + * + * The Core Engine calls this function to obtain: + * - a pointer to a memory block that will be used as the Managed Heap, + * - its total size in bytes, + * - its initial usable size in bytes (the size the Core Engine will start using, + * and may extend up to the total size as needed). + * + * The memory returned should preferably be aligned to 4 bytes, but if it is not, the framework will + * handle alignment itself by adjusting the start address and may reduce the usable size accordingly. + * + * The initial size and the total size must be set to the same value, + * unless you want to activate Automatic Heap Usage Monitoring. + * To enable Automatic Heap Usage Monitoring, set the initial size to a value + * strictly less than the total size: the framework will then start by using the + * initial size, and may extend its usage up to the total size as needed. + * + * This function is called once during Core Engine creation (i.e., when the SNI_createVM() + * function is called). + * + * This function is optional. The Core Engine provides a default weak implementation, + * which returns the address, the total size, and the initial size as defined by the application, + * typically using the .bss.microej.heap linker section and associated symbols. + * Users can override this function to provide a custom Managed Heap configuration. + * + * @param out_ptr Pointer to a void* variable to receive the address of the memory block + * to be used as the Managed Heap. + * @param out_total_size Pointer to a size_t variable to receive the total size of the + * memory block in bytes referenced by out_ptr. + * @param out_initial_size Pointer to a size_t variable that receives the initial usable + * size in bytes of the memory block. + * By default (when Automatic Heap Usage Monitoring is not desired), this value + * must be equal to the total size. + * To enable Automatic Heap Usage Monitoring, set this value lower than the + * total size. + * + * @return 0 on success, -1 on error. + */ +int LLMJVM_CONF_impl_get_managed_heap_memory(void** out_ptr, size_t* out_total_size, size_t* out_initial_size); + +/** + * @brief Optional user-implemented callback to provide a memory region for the Immortals Heap. + * + * The Core Engine calls this function to obtain: + * - a pointer to a memory block that will be used as the Immortals Heap, + * - its size in bytes. + * + * The memory returned should preferably be aligned to 4 bytes, but if it is not, the framework will + * handle alignment itself by adjusting the start address and may reduce the usable size accordingly. + * + * This function is called once during Core Engine creation (i.e., when the SNI_createVM() + * function is called). + * + * This function is optional. The Core Engine provides a default weak implementation, + * which returns the address and the size as defined by the application, + * typically using the .bss.microej.immortals linker section and associated symbols. + * Users can override this function to provide a custom Immortals Heap configuration. + * + * @param out_ptr Pointer to a void* variable to receive the address of the memory block + * to be used as the Immortals Heap. + * @param out_size Pointer to a size_t variable to receive the size of the + * memory block in bytes. + * + * @return 0 on success, -1 on error. + */ +int LLMJVM_CONF_impl_get_immortals_heap_memory(void** out_ptr, size_t* out_size); + +#ifdef __cplusplus + } +#endif