.. _Advanced_ada2java_Topics:

************************
Advanced ada2java Topics
************************

This chapter discusses a number of issues that ``ada2java`` users
should be aware of.

.. _Dealing_with_Name_Clashes:

Dealing with Name Clashes
=========================

.. index:: Name clashes

If Ada subprograms from the same package spec produce the same Java profile,
the binding generator will detect the problem and generate only the first
entity. Other entities of similar name will be ignored with a warning.
To prevent this, you can use the ``Rename`` pragma to define
the Java name corresponding to an Ada entity:

The binding generator may generate code containing 
`ambiguous operand in conversion` errors.
See :ref:`Dealing_with_ambiguous_operand_in_conversion` to solve these errors.

::

  pragma Annotate (AJIS, Rename, <identifier>, <static_string_expression>);
  
.. index:: pragma Annotate

The ``<identifier>`` argument denotes the Ada entity.
The ``<static_string_expression>`` is the name that will be used for the
corresponding Java entity generated by ``ada2java``.

Example:


::

  package Example is
    type I1 is new Integer;
    type I2 is new Integer;

    function F return I1;
    pragma Annotate (AJIS, Rename, F, "F_I1");

    function F return I2;
    pragma Annotate (AJIS, Rename, F, "F_I2");
  end Example;
  

This will result in two Java functions:


::

  int F_I1 ();
  int F_I2 ();
  

Adding a pragma to an Ada package specification is not always practical,
and indeed may be impossible if the specification is from an external library.
With GNAT-AJIS, you can provide the pragma in a separate Ada file,
applying it to an Ada entity that is itself a renaming
declaration.

This entity must be marked by another ``Annotate`` pragma:


::

  pragma Annotate (AJIS, Annotation_Renaming, <identifier>).
  

where ``<identifier>`` denotes an entity defined by an Ada renaming declaration.
The ``Annotation_Renaming`` pragma applies to all AJIS pragmas that are
specified for ``<identifier>``.


::

  package Example is
    type I1 is new Integer;
    type I2 is new Integer;

    function F return I1;
    function F return I2;
  end Example;

  with Example;
  package Renamings is
    function F return Example.I1 renames Example.F;
    pragma Annotate (AJIS, Annotation_Renaming, F);
    pragma Annotate (AJIS, Rename, F, "F_I1");

    function F return Example.I2 renames Example.F;
    pragma Annotate (AJIS, Annotation_Renaming, F);
    pragma Annotate (AJIS, Rename, F, "F_I2");
  end Renamings;
  

Entities annotated with ``pragma Annotate(AJIS, Annotation_Renaming)``
will not be mapped to Java entities;
they are assumed to be used only to define annotations.

.. _Dealing_with_ambiguous_operand_in_conversion:

Dealing with ambiguous operand in conversion errors
===================================================

.. index:: ambiguous operand in conversion

The Ada code created by the binding generator may contain "ambiguous
operand in conversion" errors.

To solve them:

- ask the binding generator to generate Ada code resolving the ambiguous
  expression (using Resolve_Ambiguous_Expression AJIS Annotate pragma)
- remove the unused possible interpretation(s) from the generated code.
  (see :ref:`Removing_function_procedure_from_binding_layer`) 

::

  pragma Annotate (AJIS, Resolve_Ambiguous_Expression, <identifier>, True);
   
.. index:: pragma Annotate

The ``<identifier>`` argument denotes the Ada entity to bind using extra code
to resolve the "ambiguous operand in conversion" error.

Example:

::

  with AJIS.Annotations; use AJIS.Annotations;

  package Example is

    type T is tagged null record;

    function F return T;
    pragma Annotate (AJIS, Resolve_Ambiguous_Expression, F, True);
 
    function F return Integer;

  end Example;

Adding a pragma to an Ada package specification is not always practical,
and indeed may be impossible if the specification is from an external library.
With GNAT-AJIS, you can provide the pragma in a separate Ada file.

::

  with AJIS.Annotations; use AJIS.Annotations;

  with Example;

  package Config is

    function F return Hello.T renames Hello.F;
    pragma Annotate (AJIS, Resolve_Ambiguous_Expression, F, True);

  end Config;

.. _Removing_function_procedure_from_binding_layer:

Removing function/procedure from binding layer
==============================================

.. index:: ambiguous operand in conversion

Any unused function/procedure can be removed from binding using the Bind
AJIS Annotate pragma.

::

  pragma Annotate (AJIS, Bind, <identifier>, False);
   
.. index:: pragma Annotate

The ``<identifier>`` argument denotes the Ada entity to remove from the
binding layer.

Example:

::

  with AJIS.Annotations; use AJIS.Annotations;

  package Example is

    type T is tagged null record;

    function F return T;
    pragma Annotate (AJIS, Bind, F, False);
 
    function F return Integer;

  end Example;

Adding a pragma to an Ada package specification is not always practical,
and indeed may be impossible if the specification is from an external library.
With GNAT-AJIS, you can provide the pragma in a separate Ada file.

::

  with AJIS.Annotations; use AJIS.Annotations;

  with Example;

  package Config is

    function F return Hello.T renames Hello.F;
    pragma Annotate (AJIS, Bind, F, False);

  end Config;


.. _Memory_Model:

Memory Model
============

.. index:: Memory model

An object on the Ada side -- a so-called *native object* -- is accessed
in Java through a *proxy object*: an instance of a class (the *proxy*
class) generated from the Ada object's type.

.. index:: Proxy object

The proxy object
contains a reference to the native object.  Invoking a member function
on the proxy object results in a call of a native subprogram on the native
object.  The native object may be either allocated or declared.

This section explains the implications of this model on the usage of the
generated binding.

.. _Requirements_for_Non-null_Parameter_Values:

Requirements for Non-null Parameter Values
------------------------------------------

If an Ada subprogram's formal parameter is not an access parameter
(i.e., it has ``in``, ``in out`` or ``out`` mode), then invoking
the corresponding Java method requires a non-null reference
to a proxy object. For example:


::

  package P is
     type T is null record;

     procedure Proc (V : out T);
  end P;
  

results in the following Java classes:


::

  public class T {
     ...
  }

  public final class P_Package {
     public static Proc (T V) {
        ...
     }
     ...
  }
  

You need to ensure that the ``V`` parameter passed to ``Proc`` is
not ``null``. Hence, the following will throw an exception, since
``v`` is implicitly initialized to ``null``:


::

  T v;
  P_Package.Proc (v);
  

A simple way to provide a non-null reference is to initialize it to an
allocated object:


::

  T v = new T ();
  P_Package.Proc (v);
  

.. _Allocating_Ada_Objects_from_Java:

Allocating Ada Objects from Java
--------------------------------

If ``A`` is an Ada type that is mapped by ``ada2java`` to a
Java class ``J``, then the execution of a Java constructor ``J()``
will create two objects:

* 
  A Java object (the 'proxy' object) of class ``J``,
  allocated on the Java heap and subject to Garbage Collection by the JVM, and
* 
  An Ada object of type ``A``, allocated on the Ada heap, referenced from the
  proxy object.

.. _Automatic_Creation_of_Native_Objects:

Automatic Creation of Native Objects
------------------------------------

Under certain circumstances, the generated Java code may construct extra
native objects on the Ada heap. To help explain this, here is an example where
such allocation is not needed, namely, a function returning an access value:


::

  package P is
     type T is record ... end record;

     type T_Acc is access all T;

     function Create_T_Acc return T_Acc;
  end P;
  

The generated code will look like:


::

  public class T { ...}

  public final class P_Package {
     final public T Create_T_Acc () { ...}
     ...
  }
  

On the Java side, the method ``Create_T_Acc`` returns a
proxy object that contains the value of the pointer returned by
the call of the Ada function. So the user can write:


::

  T v = P_Package.Create_T_Acc ();
  

and then access the data of ``v``. Note that all the standard precautions
that apply in using an Ada pointer have to be taken in
this case as well. In particular, after the object has been freed on the
Ada side, there
should be no further references to it from Java. The
Ada programmer needs to document how the returned value should or should not
be used, and the Java programmer needs to adhere to these guidelines.

However, a function returning a record rather than an access value raises
additional issues:


::

  package P is
     type T is record ... end record;

     function Create_T return T;
  end P;
  

results in a default class similar to the one in the previous example:


::

  public final class P_Package {
     final public T Create_T () { ... }
     ...
  }
  

The Java programmer can write:


::

  T v = P_Package.Create_T ();
  

But in this case, the value returned by the function is not a pointer.
A new Ada native object is automatically allocated on the heap, initialized
to a copy of the value returned by the Ada function,
and is referenced through the proxy object constructed by the Java method
``Create_T``.
This is similar to the Ada situation where calling ``Create_T_Acc`` would
not involve a copy of a ``T`` object, whereas ``Create_T`` would.

Because of implementation constraints there may be more than one
copy involved in the call of ``Create_T`` (but only one native object
will be created on the heap). This will be discussed further in
:ref:`Clone_and_Copy_Semantics`.

.. _Native_Ownership:

Native Ownership
----------------

.. index:: Ownership (of native objects)

As illustrated above, native objects may be created automatically by
Java methods corresponding to Ada subprograms. This raises the issue of
when/how such objects are to be deallocated.

In general, the ``ada2java`` approach is based on the following
principles:

* 
  The environment (Java or Ada) that allocates an object is responsible for its
  deallocation;

* 
  In Java, all deallocation is performed implicitly, by the Garbage Collector;

* 
  In Ada, the programmer is responsible for manually deallocating the objects;

* 
  Dangling references should be prevented; i.e., the Ada object should not
  be deallocated as long as there are still live references to the object.

A native object created from Java is said to be *owned* by its proxy object.
It has been created by the Java program, and it must be freed
by the Java environment.

Such an object is tightly linked to its proxy -- when the proxy object doesn't
exist (i.e. is garbage collected), the native object becomes
inaccessible. [#]_

.. index:: Proxy object

The native object deallocation
will occur automatically, when the Java proxy is garbage collected (more
specifically through the implementation of the ``finalize`` method).

A native object not owned by a proxy -- for example, one that has been
obtained from the Ada API through an Ada pointer -- will not be deleted
automatically.

The ownership state of a native object may be queried through the
``getOwner`` method.

.. index:: getOwner method

This function returns a value from the enumeration
``com.adacore.ajis.IProxy.Owner``, either ``NATIVE`` or ``PROXY``,
specifying who is responsible for managing the memory. For example after these
assignments:

.. index:: com.adacore.ajis.IProxy.Owner type


::

  T v1 = new T ();
  T v2 = P_Package.Create_T_Acc ();
  T v3 = P_Package.Create_T ();
  

the following relationships hold:

+--------------------+------------+
| ``v1.getOwner ()`` | ``PROXY``  |
+--------------------+------------+
| ``v2.getOwner ()`` | ``NATIVE`` |
+--------------------+------------+
| ``v3.getOwner ()`` | ``PROXY``  |
+--------------------+------------+

Native objects referenced by ``v1`` and
``v2`` will be deallocated when the corresponding Java proxy is
garbage-collected.

You may change the owning attribute of a referenced native object,
through the ``setOwner`` method of proxy classes.

.. index:: getOwner method

This should
be used very carefully, as it may generate memory leaks or corruption. Doing
the following:


::

  T v1 = new T ();
  v1.setOwner (Owner.NATIVE);
  

will deactivate the object deallocation on finalization. The Java programmer
becomes responsible for explicitly deallocating the native object.

Note that, while moving the owning from PROXY to NATIVE is a relatively safe
operation, raising the possibility of memory leaks but not object corruption,
moving in the opposite direction should be done with great care.
A object managed by the NATIVE
side may be deallocated by the Ada application at any moment, or be declared
as the field of another object or even on the native stack in situations
such as callbacks. If it's not clear where the object is coming from,
cloning it (resulting automatically into an object managed by the proxy)
is often the best solution.

As will be described below, only objects that are known to be managed
though pointers can have their ownership changed. An object obtained,
for example, from a global variable or field will need to retain its
known ownership.

.. _Object_Allocators:

Object Allocators
-----------------

The generated code keeps track of how native objects have been obtained, and
restricts their operations accordingly. Three possible
allocators are recognized:



*DYNAMIC*
  Such objects are created either through bound constructors, accessed from
  native access types, or through an automatic copy from the bound code.
  The ownership of dynamic objects can be changed.


*STATIC*
  Such objects are accessed from global variables, fields, or callback
  parameters that are not access types. The ownership of these objects is
  always ``NATIVE`` and cannot be changed.


*UNKNOWN*
  In some cases, for example on copying values of tagged types, it is not
  possible to determine whether the object has been allocated statically or
  dynamically. In such cases
  you can access the allocator through which an object is referenced using
  the ``IProxy.getAllocator ()`` function.

  .. index:: IProxy.getAllocator function


.. _Restrictions_on_Proxy-Owned_Objects_Passed_to_Subprograms:

Restrictions on Proxy-Owned Objects Passed to Subprograms
---------------------------------------------------------

Passing a (reference to a) native object as an actual parameter to an Ada
subprogram whose corresponding formal parameter is either an access parameter
or of an access type
could in some cases result in a dangling reference to the native object,
whereas in other situations it might be harmless.
In order to provide the desired safety while allowing the needed generality,
``ada2java``'s approach is similar to the way that the Ada standard
supplies both the ``'Access`` and ``'Unchecked_Access`` attributes
for composing pointers to data objects.

In summary, when the Java side is responsible for pointer memory management
(i.e. the object is owned or it is accessed through ``'Access`` or
``'Unrestricted_Access``), then
an exception will be thrown in Java on an attempt
to pass a reference to a native object as an actual parameter when the formal
is of a named or anonymous access type.
However, this check can be suppressed either locally (for a given formal
parameter) or globally (for all calls).

Here is a summary of the troublesome scenario:

* A reference to a proxy object is passed as a parameter to a Java method,
  and the reference to the corresponding native object is then passed to a
  native Ada subprogram  whose formal is an access parameter or of an access
  type;
* The Ada subprogram copies the parameter to a global variable and
  ultimately returns;
* The proxy object ultimately becomes inaccessible and is garbage
  collected by the JVM;
* The native object is deallocated as an effect of the proxy object's
  finalization;
* The deallocated object is still designated by the global variable.

To prevent this, an exception is thrown at step 1 above.

Here is an example:


::

  -- Original Ada package
  package P is
     type T is
        record
           A, B : Integer;
        end record;

     type A_T is access all T;

     G : A_T;

     procedure Set_G (V : A_T);
  end P;

  package body P is
     procedure Set_G (V : A_T) is
     begin
        G := V;
     end Set_G;
  end P;
  


::

  // Java statements
  T v = new T ();
  P_Package.Set_G (v); // Throws an exception
  

If the invocation of ``Set_G`` did not throw an exception,
``G`` would become a dangling pointer when the proxy object
referenced by v is garbage collected.

However, if the invocation of ``Set_G`` did not cause an assignment of its
formal parameter ``V`` to a global variable, then passing ``v`` as an
actual parameter would be harmless.
``ada2java`` allows the Ada API to enable such uses, and thus to
deactivate the check:


::

  pragma Annotate (AJIS, Assume_Escaped, <Condition>, <Subprog>, <Formal_Param>)
  
.. index:: Assume_Escaped (argument to pragma Annotate)

where:

* ``<Condition>`` is either ``True`` or ``False``

* ``<Subprog>`` is the name of the Ada subprogram

* ``<Formal_Param>`` is the affected formal parameter, expressed as a
  ``String`` literal

When ``<Condition>`` is ``False``, the Ada subprogram is responsible for
ensuring that the formal parameter is not copied to a global variable, or used
to set a field of a structure that will be used outside of the scope of the
subprogram.  When ``<Condition>`` is ``True``, an exception is thrown when a
proxy object is passed as an actual parameter to the  ``<Formal_Param>``
parameter of ``<Subprog>``.

Here is an example:


::

  package P is
     type T is
       record
          A, B : Integer;
       end record;

     type A_T is access all T;

     G : A_T;

     procedure Safe_Set_G (V : A_T);
     pragma Annotate (AJIS, Assume_Escaped, False, Safe_Set_G, "V");
  end P;

  package body P is
     procedure Safe_Set_G (V : A_T) is
     begin
        G := new T'(V.all);
     end Safe_Set_G;
  end P;
  


::

  *// Java statements*
  T v = new T ();
  P_Package.Safe_Set_G (v); *// OK*
  

The invocation ``Safe_Set_G (v)`` is safe since the Ada subprogram does not
let the formal parameter 'escape'.

The 'escaped' checks can be globally activated through the ``ada2java``
switch
``--assume-escaped``, and globally deactivated through the switch
``--no-assume-escaped``.

.. index:: --assume-escaped option (for ada2java)

.. index:: --no-assume-escaped option (for ada2java)

The default is ``--assume-escaped``. An explicit pragma overrides
the global configuration switch.

Note that canceling escape checks should be done with great care, as there
is no way to ensure that no escaping has occurred. In many situations,
the programmer's intent is to create an object on the Java
side and then store the object on the native side. In such a case, canceling
proxy ownership through the ``IProxy.setOwner`` method will have the
desired effect, for example:


::

  // Java statements
  T v = new T ();
  v.setOwner (Owner.NATIVE);
  P_Package.Set_G (v); // OK
  

.. _Parameter_Mode_Documentation:

Parameter Mode Documentation
----------------------------

ada2java documents the mode of the parameters generated by the binding. This
mode is only documented for proxies, not scalar values. The following modes
are possible:



*passed by value*
  The object is passed by value. In calls from Java to Ada, it means that the
  proxy cannot be null. Proxy or native ownership doesn't matter. In callbacks
  implemented in Java, proxies for these parameters will be natively-owned
  and statically allocated. For returned value, the returned Ada object is
  copied to the returned proxy.


*passed by reference (escapable)*
  The object is passed by reference, and potentially escaped by the Ada code.
  The object has to be natively owned and dynamically allocated.


*passed by reference (non escapable)*
  The object is passed by reference, but is known not to be escaped by the
  native code. Any proxy can by passed to parameters of that type. When
  implementing a callback with a parameter of this type, or for returned values,
  the proxy will be natively owned and dynamically allocated.


*passed by reference (static)*
  The object is passed by reference, but its reference is coming from a location
  place, typically a global variable or a field. This only applies to returned
  values. The returned proxy will be natively owned and statically allocated.


.. _Aliasing:

Aliasing
========

.. index:: Aliasing

As explained in the previous chapter, Ada object are managed through Java
proxies. The creation of such proxies is obtained through an access type. For
example, in the following code:


::

  package P is
     type T is
       record
          A, B : Integer;
       end record;

     V1 : aliased T;

     type T2 is record
        V2 : aliased T;
     end record;

     type A is array (Integer range <>) of aliased T;

     V3 : aliased A (1 .. 10);
  end P;
  

the binding generator will generate accessors to V1, V2 and V3 so that fields
of T can be modified directly. It's possible to write:


::

  V1 ().A (1);

  T2 v = new T2 ();
  v.A (2);

  V3 ().Get_Element_At (10).A (3);
  

Accessing variables generate a proxy pointing directly to the address in
memory. These proxies can be manipulated on their own, as any other, for
example:


::

  T ptr = V1 ();
  ptr.A(1);
  

In the above example, ptr is a Java proxy containing a pointer to the global
variable V. Such a pointer would typically be obtained through a ``'Access``
applied on the Ada variable V1.

It's sometimes unconvenient to declare aliased data just for the purpose of
binding generation. GNAT offers a mechanism to retreive an access to any
piece of data, ``'Unrestricted_Access``. The use of such method is however
dangerous. On certain architectures, e.g. *sparc-solaris*, forcing to
retreive an access on a missaligned data will issue a program crash. In
order to avoid that, by default, ada2java does not generate such accesses and
create proxies only on aliased data.

This behavior can be deactivated with the ada2java argument
``--unaliased-access``, which will allow access to unaliased data.
Making data aliased should always be prefered to the use of that option.

.. _Thread_Safety:

Thread Safety
=============

.. index:: Thread safety

By default, the generated Java code is thread-safe, with locking logic
that prevents multiple Java threads from accessing native methods
at the same time.  In summary, a Java method in a proxy object acquires a
lock (a binary semaphore) before invoking the corresponding native method,
and releases
the lock when the native method returns (either normally or abnormally).
The semaphore is global versus per Ada package; e.g. different Java threads
are not allowed to invoke native methods simultaneously even if the native
methods correspond to subprograms from different packages.

Even if the Java application does not explicitly create
any threads, there are still two threads -- the main (user) thread and the
garbage collector; thus locking is needed in this case also.

The default locking behavior is not always appropriate, however.
In particular, if the native
code is using tasking, with mutual exclusion enforced on the Ada side, then
there is no need for locking in the Java code (and indeed such locking could
have undesirable consequences including deadlock).

User control over the generation of locking code is obtained through the
following pragma:


::

  pragma Annotate (AJIS, Locking, <Subprogram>, <LockControl>);
  
.. index:: Locking (argument to pragma Annotate)

where ``<Subprogram>`` is the subprogram name, and
``<LockControl>`` is one of ``Disable``, ``Check`` and ``Protect``.



``Protect``
  Default setting.
  The generated code automatically brackets each invocation of the named native
  ``<Subprogram>`` within a ``lock`` ... ``unlock`` region.
  If a thread ``t1`` invokes ``<Subprogram>`` while some other thread ``t2``
  holds the lock,
  then ``t1`` will be queued until the lock is released.
  Thus simultaneous calls of native methods are permitted but will entail
  queuing.


``Disable``
  The generated code contains no locking around invocations of ``<Subprogram>``,
  and one thread may invoke ``<Subprogram>`` while some other thread is executing
  a native method (even one whose ``LockControl`` is ``Protect``.


``Check``
  The generated code contains no locking around invocations of ``<Subprogram>``,
  and the application must ensure that any such invocation is within a
  ``lock`` ... ``unlock`` region.
  An exception is thrown if a thread invokes ``<Subprogram>`` without holding
  the lock.

The following examples illustrate the multithreading behavior and the effects
of the ``<LockControl>`` argument to the pragma.


::

  package P is
     procedure P1 (I : Integer);
     pragma Annotate (AJIS, Locking, P, Disable);

     procedure P2 (I : Integer);
     pragma Annotate (AJIS, Locking, P, Disable);
  end P;
  

Concurrent invocations of ``P1`` and ``P2`` are allowed (i.e.,
locking code is not generated automatically).

Code protected by the lock can be provided by hand by the
Java developer. The lock is created in the library class generated for the
binding, ``<base_package>.Ada2Java.Library``, under the identifier
``lock``. Thus:


::

  import base.P_Package;
  import base.Ada2Java.Library;

  public class Main {
     public static void main (String [] args) {
        Library.lock.lock ();

        try {
           P_Package.P1 (0);
           P_Package.P2 (0);
        } finally {
           Library.lock.unlock ();
        }
     }
  }
  

Following standard Java coding style,
the ``lock`` / ``unlock`` logic should always appear in a ``try`` ...
``finally`` block,
in order to release the lock even if an unexpected exception is propagated.

In certain cases, locking is required but the logic is more complex than
simply protecting each native method invocation with a semaphore.
For example, it may be necessary to invoke a sequence of native methods as
an atomic action.
This effect can be achieved through the ``Check`` setting for
*LockControl*:


::

  package P is
     procedure P1 (I : Integer);
     pragma Annotate (AJIS, Locking, P1, Check);

     procedure P2 (I : Integer);
     pragma Annotate (AJIS, Locking, P2, Check);
  end P;
  

The Java program has to acquire the library lock before attempting any native
call. Invoking ``P1`` or ``P2`` outside of a section protected by the
lock will throw a Java exception.

The locking behavior can be changed globally through the ``ada2java``
``--[no-]locking`` switch. More specifically,
here are the permitted values for this switch:

.. index:: locking option (for ada2java)

.. index:: no-locking option (for ada2java)



``--locking-protect``
  Default setting; globally sets *LockControl* as ``Protect`` for all
  subprograms.

``--locking-check``
  Globally sets *LockControl* as ``Check`` for all subprograms.

``--no-locking``
  Globally disables locking (i.e., sets *LockControl* as ``Disable``
  for all subprograms).

Note that an AJIS `Locking` pragma takes precedence over the global
switch.

The ``finalize`` method invoked during garbage collection does not
correspond to a subprogram from the Ada package that is input to
``ada2java``, and it is not affected by the ``--[no-]locking`` switch.
Instead, the locking logic used for the ``finalize`` call of Java
proxies during garbage collection is determined by the
``--[no-]locking-finalize`` switch:

.. index:: locking-finalize option (for ada2java)

.. index:: no-locking-finalize option (for ada2java)



``--locking-finalize-protect``
  Default setting; sets *LockControl* as ``Protect`` for ``finalize``.

``--locking-finalize-check``
  Sets *LockControl* as ``Check`` for ``finalize``.

``--no-locking-finalize``
  Disables locking (i.e., sets *LockControl* as ``Disable``
  for ``finalize``)

A typical usage of these two switches would be to set ``Check`` as the
*LockControl* for all subprograms, and ``Protect`` as the
*LockControl* for ``finalize`` methods:


::

  ada2java --locking-check --locking-finalize-protect p.ads
  

.. _Proxies_and_Native_Object_Equality:

Proxies and Native Object Equality
==================================

.. index:: Native object equality

.. index:: Equality

Proxy classes are generated with an ``equals`` implementation that calls the
corresponding Ada ``=`` operation. For example:


::

  package P is
     type T is
        record
           F : Integer;
        end record;
  end P;
  

The proxy class can be used as follows:


::

  T v1 = new T ();
  T v2 = new T ();
  v1.F (0); // "setter" method for field F
  v2.F (0); // "setter" method for field F
  

and now the result of ``v1.equals (v2)`` is ``true``.
This corresponds to 'shallow' equality, in contrast with ``==`` which
tests pointer identity.

A new proxy is created each time a native function
returns a pointer. For example:


::

  package P is
     type T is null record;
     type A_T is access all T;
     G : A_T := new T;
     function Return_G return A_T;
  end P;

  package body P is
     function Return_G return A_T is
     begin
        return G;
     end Return_G;
  end P;
  


::

  AT p1 = P_Package.Return_G ();
  AT p2 = P_Package.Return_G ();
  

Now ``p1 == p2`` is ``false``,
since a new proxy is created by each function return,
but ``p1.equals (p2)`` is ``true``,

The association between a proxy and its native object is lost when the
proxy is passed to a native method. For example:


::

  package P is
     type T is null record;
     type A_T is access all T;
     function Return_This (This : A_T) return A_T;
  end P;

  package body P is
     function Return_This (This : A_T) return A_T is
     begin
        return This;
     end Return_G;
  end P;
  


::

  T v = new T ();
  

Now the result of ``(v == P_Package.Return_This (v))`` is ``false``

Java reference equality has special semantics in the case of
cross-language inheritance, due to the use of a shadow native object -- see
:ref:`Shadow_Object_Equality` for more details.

.. _Clone_and_Copy_Semantics:

Clone and Copy Semantics
========================

.. index:: Clone and copy semantics

A proxy class generated from a non-limited Ada type includes a ``clone``
method. The base class for all proxies, ``AdaProxy``, implements the
``Cloneable`` interface, and defines a public method ``clone``.

.. index:: AdaProxy class

.. index:: clone method (in AdaProxy class)

The ``clone`` method performs a 'shallow copy' of all the fields, except
for the native object reference.
The native object reference in the cloned proxy
is a pointer to a newly allocated Ada object.
This new native object is itself a shallow copy of the original native object.

Thus cloning a proxy does not result in the sharing of the native object by
the original proxy and the cloned proxy.
The latter points to a new native object.
This behavior is needed to avoid a dangling reference (to the native object)
when the original
proxy is garbage collected.

If the proxy class corresponds to a limited type, then the generated
clone method
will throw an exception.

Additional semantics for clone and copy, in connection with
cross-language inheritance,
are covered below (see :ref:`Shadow_Object_Cloning`).

.. _Cross-Language_Inheritance:

Cross-Language Inheritance
==========================

.. index:: Inheritance (cross-language)

This section discusses a number of issues related to cross-language
inheritance; i.e., defining a Java class as an extension of a proxy
class for an Ada tagged type.

.. _Inheriting_from_a_Java_Proxy:

Inheriting from a Java Proxy
----------------------------

As explained in :ref:`Tagged_Types`, ``ada2java`` maps an Ada tagged type
to a non-final Java proxy class. You can extend this class in Java.
For example:


::

  package P is
     type T is tagged null record;

     procedure Prim (V : T);
  end P;
  

results in the following Java class:


::

  public class T {
     public void Prim () {
        ...
     }
     ...
  }
  

which may be extended, with the instance method overridden:


::

  public class T_Child extends T {
     public void Prim () {
        ...
     }
  }
  

An object of the subclass ``T_Child`` is also a proxy; constructing such an
object allocates a native object, referred to as a 'shadow native object'.
Its properties will be
described below (:ref:`The_Shadow_Native_Object`).

The Java program can then invoke the ``Prim`` method, with
standard Java dispatching behavior.  For example:


::

  T v1 = new T ();
  T v2 = new T_Child ();

  v1.Prim (); // Will call the native Prim
  v2.Prim (); // Will call the overridden Java Prim
  

.. _Cross_Language_Dispatching_from_Ada:

Cross Language Dispatching from Ada
-----------------------------------

A method overridden in Java can be called in Ada using the usual Ada
dispatching mechanism. For example:


::

  package P is
     type T is tagged null record;

     procedure Prim (V : T);

     procedure Call_Prim (V : T'Class);
  end P;

  package body P is

     procedure Prim (V : T) is
     begin
        --  Native Prim implementation;
     end Prim;

     procedure Call_Prim (V : T'Class) is
     begin
        Prim (V); -- Dispatching call.
     end Call_Prim;

  end P;
  

The invocation of ``Prim`` in ``Call_Prim`` is dispatching, and
the ``Prim`` for the type of the actual parameter
will be called. In Java, this procedure can be used in conjunction with
a cross-language extension of T, e.g.:


::

  class T_Child extends T {
     public Prim () {
        ...
     }
  }

  T v = new T_Child ();
  P_Package.Call_Prim (v);
  

The Java program is invoking the native Ada ``Call_Prim`` procedure, which
in turn dispatches to the Java method ``Prim`` in ``T_Child``.

.. _The_Shadow_Native_Object:

The Shadow Native Object
------------------------

.. index:: Shadow native object

This section describes in more detail the semantics of the shadow native
object.

.. _Basic_Properties:

Basic Properties
^^^^^^^^^^^^^^^^

As seen above,
cross-language dispatching is supported; an Ada dispatching call may result
in the invocation of a Java method on a proxy object.
This is possible because of the *shadow native object* concept.

For any tagged type ``T`` declared in a package spec that is input to
``ada2java``, a new type is automatically generated that extends ``T``
with a component that references a proxy object.  The Ada declaration is:


::

  type Shadow_T is new T with
     record
        Link_To_Proxy : Java_Object;
     end record;
  

If ``T_Child`` is a Java class that extends ``T``, then
constructing an instance of ``T_Child`` will create
a native ``Shadow_T`` object instead of a regular ``T`` object.
This type overrides every controlling primitive of T, and delegates the
dispatching to the
Java side. If a method corresponding to an Ada primitive operation is not
overridden in Java, then the subprogram from
the parent Ada type will be automatically called.

The use of a shadow object introduces a tight relationship between a Java
proxy and its Ada native object. Basically, there is a roundtrip dependency
between the two, so that a Java proxy object is associated with a unique Ada
shadow native object and vice versa.

This has several non-trivial implications that are described in the sections
below.

.. _Memory_Management:

Memory Management
^^^^^^^^^^^^^^^^^

.. index:: Memory management

The reference from the shadow native object to the Java object is called
a *global reference*. [#]_

.. index:: Global reference

There are two kinds of global references: regular (usually simply
referred to as global references) and weak. A regular global reference
prevents the object from being garbage collected, whereas a weak global
reference does not.

.. index:: Regular global reference

.. index:: Weak global reference

When a native object is owned by its proxy, the proxy is responsible for
releasing the native memory. In this case, the reference from the native
object to the proxy is a weak global reference: garbage collection will not be
prevented, and both the proxy and then the native object will be released upon
collection.

However, when the native object is owned by the native side, then the native
object may continue to exist even if the proxy has become inaccessible from
Java. In such a case, a global reference is used, so that the garbage collector
is prevented from collecting the Java object. Such a global reference will be
automatically released when the Ada object is actually deallocated.

Forcing the deallocation of the native object through
``IProxy.deallocateNativeObject`` will release the global reference as well.

Switching the owner of the native object between
NATIVE and PROXY will switch the reference from a regular global reference to
a weak one.

In order to avoid a potential memory leak, the link between the shadow native
object and the Java proxy has to be broken manually when the shadow native
object is no longer needed on the Ada side.  This may be done in two ways:

* Deallocating the native shadow object, from Ada.
* Invoking the ``unlink`` method on the proxy, from Java

.. _Shadow_Object_Equality:

Shadow Object Equality
^^^^^^^^^^^^^^^^^^^^^^

Java reference equality (``==``) is not consistent with native pointer
equality, but Java object equality (``equals``) is.
That is, if ``A`` and ``B`` are two native pointers where ``A = B``,
then on the Java side ``A.equals(B)`` is ``true`` but ``a==b`` is
``false``.

However, since the association between shadow object and proxy is one-to-one,
proxy equality is meaningful. For example:


::

  package P is
     type T is tagged null record;
     type T_Access is access all T'Class

     procedure Identity (Item : T_Access) return T_Access;
     -- Returns Item as its result
  end P;
  

On return from ``Identity``, the 'glue code' between Java and Ada will
check if the returned value is a shadow native object and, if so, will return
the corresponding Java proxy instead of creating a new one. Hence the
following fragment


::

  public class T_Child extends T {
  }

  T v = new T_Child ();
  

will result in the expression ``P_Package.Return_This (v) == v``
delivering ``true``.

.. _Shadow_Object_Cloning:

Shadow Object Cloning
^^^^^^^^^^^^^^^^^^^^^

Cloning from Java will result in copying a native object. In the case of
a shadow native object, there will be a new shadow object as well, referencing
the newly created java proxy, thus preserving the one-to-one relationship
between the shadow native object and the proxy.

However, there are cases where copies are made from Ada as well:


::

  package P is
     type T is tagged null record;
     type T_Access is access all T'Class

     procedure Duplicate (Item : T_Access) return T_Access;
  end P;

  package body P is

     procedure Duplicate (Item : T_Access) return T_Access is
     begin
        First_Copy  : T'Class  := Item.all;
        Second_Copy : T_Access := new T'Class'(Item.all);
     begin
        return Second_Copy;
     end Duplicate;

  end P;
  

Calling ``Duplicate`` from Java will lead to two shadow object copies,
one on the stack (``First_Copy``) and one on the heap
(``Second_Copy.all``).  As explained earlier, the
link between the shadow native object and the proxy will be deleted when
the Ada object is deallocated, at the exit of ``Duplicate`` for the
``First_Copy`` variable.

The ``Second_Copy`` proxy created in the copy process will be returned by
the Java method corresponding to the ``Duplicate`` procedure.

Note that a proxy created by such a copy does not own its Ada native object.

Proxy cloning from Ada does not involve a ``clone`` invocation from the Java
extended object. If the Java code needs to perform a deep copy in the
Java proxy, the method ``void proxyCloned (IProxy initialObject)`` should
be overridden instead. The default ``clone`` implementation of the generated
Java classes will call this method as well.

*Limitation:* when ``proxyCloned`` is called from Ada, the link
between proxy and native object
is not yet established.  Thus ``proxyCloned`` is not allowed to invoke
any native methods.
The Ada type may be derived from ``Finalization.Controlled``, and
``Adjust`` may be overridden, to work around this limitation.

Note that multiple copies -- and thus repeated proxy creation -- may be
involved when a (non-access) shadow object is returned. For example:


::

  package body P is

     function Identity (Item : T_Access) return T'Class is
     begin
        return Item.all;
     end Identity;

  end P;
  

Due to internal machinery, three copies may be needed in the implementation
of the return from this function when called from Java. If it is necessary to
ensure that only one copy is performed, then the Ada function should be written
as a wrapper for an Ada access-returning function.

.. _Controlled_Types:

Controlled Types
----------------

.. index:: Controlled types

A class that is generated from an Ada controlled type may be extended
in Java, with overriding versions of the ``Adjust``, ``Finalize``,
and/or ``Initialize`` methods.

A current limitation is that ``Initialize`` cannot be called on a shadow
object, e.g.:


::

  package P is

     type T is new Controlled with null record;

     procedure Initialize (This : in out T);

  end P;
  

can be used in:


::

  class T_Child extends T {

     void Initialize () {

     }

  }

  T v = new T_Child ();
  

But the overridden ``Initialize`` will not be called by the constructor.

This limitation will be removed in a future release.

.. _Managing_Attachment_to_Java_Proxies:

Managing Attachment to Java Proxies
===================================

By default, subprograms (except controlling primitives) are not attached --
they are placed in the default class ``<Ada_Package_Name>._Package``.

.. index:: Default class

However, when all of the following conditions are met, a subprogram is
attachable to the class corresponding to its first parameter:

* 
  The first parameter of the subprogram has one of the following forms:

  * A private type or a record type,
  * An access type (of mode ``in``) designating a private or record
    type, or
  * An access parameter designating a private or record type.

* 
  The type of this parameter -- or of the designated type if an access
  parameter -- is declared in the same package spec as the subprogram.

A subprogram that meets these criteria can be mapped to a method
defined in the class corresponding to the first parameter's type, and
the value of this first parameter will come from the hidden parameter
``this``.

This attachment is activated by the annotation pragma ``Attached``:


::

  pragma Annotate (AJIS, Attached, <Condition>, <Subprogram>);
  

Example:


::

  package Example is
     type Rec is null record;
     procedure Proc (V : Rec; I : Integer);
     pragma Annotate (AJIS, Attached, True, Proc);
  end Example;
  

will map to the class


::

  public class Rec extends com.adacore.ajis.internal.ada.AdaProxy {
    ...
    public void Proc (int I){...}
  }
  

Attachment policies may be globally turned on / off using the following
switches:



``--[no-]attach-parameter``

  .. index:: --attach-parameter option (for ada2java)

  .. index:: --no-attach-parameter option (for ada2java)

  Activates or deactivates 'best-effort' attachment to the class corresponding
  to the first parameter. When this is set,
  ``ada2java`` will try to perform subprogram attachment whenever
  possible. Default is ``--no-attach-parameter``.


``--[no-]attach-access``

  .. index:: --attach-access option (for ada2java)

  .. index:: --no-attach-access option (for ada2java)

  Activates or deactivates attachment for
  access type. When activated, subprograms with an access type (named or
  anonymous) for their first parameter
  will be attached. (Note, however, that such attachment prevents
  passing a ``null`` value, since ``this`` is always the implicit
  parameter.) Default is ``--no-attach-access``.


``--[no-]attach-controlling``

  .. index:: --attach-controlling option (for ada2java)

  .. index:: --no-attach-controlling option (for ada2java)

  Activates or deactivates attachment
  of controlling primitives. This is required for cross language inheritance.
  Default is ``--attach-controlling``.


``--[no-]attach-ada2005``

  .. index:: --attach-ada2005 option (for ada2java)

  .. index:: --no-attach-ada2005 option (for ada2java)

  Activates or deactivates attachment based on applicability of Ada 2005 prefix
  notation.
  With the ``--attach-ada2005`` switch, ``ada2java`` will attempt
  to attach a subprogram (define it in the class corresponding to the initial
  parameter) that would otherwise be placed in the default package,
  if it can be invoked via Ada 2005 prefix notation.
  Default is ``--no-attach-ada2005``.

In the example below, attachment is requested for everything except
noncontrolling initial access parameters:


::

     ada2java --attach-parameter --no-attach-access p.ads
  

Pragma ``Attached`` takes precedence over the global switch.

.. _Exceptions_propagation:

Exceptions propagation
======================

.. index:: Exception propagation

Exceptions raised from Ada are translated into instances of the relevant
descendant of class ``com.adacore.ajis.NativeException``
(see :ref:`Exceptions`) and propagated to Java.

.. index:: com.adacore.ajis.NativeException

Exceptions raised from a Java
callback are translated back to the original Ada exception - or to
Java_Exception declared in the AJIS.Java package, and propagated to Ada.

-------------------------------------------------------------------------------

.. rubric:: Footnotes

.. [#] 

As will be described below, cloning the proxy object has special semantics
so that the native object gets copied, not only its reference.

.. [#] 

An explanation of global references may
be found in Liang's {The Java Native Interface Programmer's Guide and
Specification}, Chapter 5.
