Adding adoc files & several conversion errors fixed
This commit is contained in:
parent
e836ecfd7c
commit
372438de0a
35 changed files with 5959 additions and 0 deletions
141
en-US/Java-LowLevel.adoc
Normal file
141
en-US/Java-LowLevel.adoc
Normal file
|
@ -0,0 +1,141 @@
|
|||
|
||||
:experimental:
|
||||
|
||||
[[sect-Defensive_Coding-Java-LowLevel]]
|
||||
==== Low-level Features of the Virtual Machine
|
||||
|
||||
[[sect-Defensive_Coding-Java-Reflection]]
|
||||
===== `Reflection and Private Parts`
|
||||
|
||||
The `setAccessible(boolean)` method of the
|
||||
`java.lang.reflect.AccessibleObject` class
|
||||
allows a program to disable language-defined access rules for
|
||||
specific constructors, methods, or fields. Once the access
|
||||
checks are disabled, any code can use the
|
||||
`java.lang.reflect.Constructor`,
|
||||
`java.lang.reflect.Method`, or
|
||||
`java.lang.reflect.Field` object to access the
|
||||
underlying Java entity, without further permission checks. This
|
||||
breaks encapsulation and can undermine the stability of the
|
||||
virtual machine. (In contrast, without using the
|
||||
`setAccessible(boolean)` method, this should
|
||||
not happen because all the language-defined checks still apply.)
|
||||
|
||||
This feature should be avoided if possible.
|
||||
|
||||
[[sect-Defensive_Coding-Java-JNI]]
|
||||
===== Java Native Interface (JNI)
|
||||
|
||||
The Java Native Interface allows calling from Java code
|
||||
functions specifically written for this purpose, usually in C or
|
||||
C++.
|
||||
|
||||
The transition between the Java world and the C world is not
|
||||
fully type-checked, and the C code can easily break the Java
|
||||
virtual machine semantics. Therefore, extra care is needed when
|
||||
using this functionality.
|
||||
|
||||
To provide a moderate amount of type safety, it is recommended
|
||||
to recreate the class-specific header file using
|
||||
[application]*javah* during the build process,
|
||||
include it in the implementation, and use the
|
||||
[option]`-Wmissing-declarations` option.
|
||||
|
||||
Ideally, the required data is directly passed to static JNI
|
||||
methods and returned from them, and the code and the C side does
|
||||
not have to deal with accessing Java fields (or even methods).
|
||||
|
||||
When using `GetPrimitiveArrayCritical` or
|
||||
`GetStringCritical`, make sure that you only
|
||||
perform very little processing between the get and release
|
||||
operations. Do not access the file system or the network, and
|
||||
not perform locking, because that might introduce blocking.
|
||||
When processing large strings or arrays, consider splitting the
|
||||
computation into multiple sub-chunks, so that you do not prevent
|
||||
the JVM from reaching a safepoint for extended periods of time.
|
||||
|
||||
If necessary, you can use the Java `long` type
|
||||
to store a C pointer in a field of a Java class. On the C side,
|
||||
when casting between the `jlong` value and the
|
||||
pointer on the C side,
|
||||
|
||||
You should not try to perform pointer arithmetic on the Java
|
||||
side (that is, you should treat pointer-carrying
|
||||
`long` values as opaque). When passing a slice
|
||||
of an array to the native code, follow the Java convention and
|
||||
pass it as the base array, the integer offset of the start of
|
||||
the slice, and the integer length of the slice. On the native
|
||||
side, check the offset/length combination against the actual
|
||||
array length, and use the offset to compute the pointer to the
|
||||
beginning of the array.
|
||||
|
||||
[[ex-Defensive_Coding-Java-JNI-Pointers]]
|
||||
.Array length checking in JNI code
|
||||
====
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/Java-JNI-Pointers.xml"
|
||||
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
In any case, classes referring to native resources must be
|
||||
declared `final`, and must not be serializeable
|
||||
or cloneable. Initialization and mutation of the state used by
|
||||
the native side must be controlled carefully. Otherwise, it
|
||||
might be possible to create an object with inconsistent native
|
||||
state which results in a crash (or worse) when used (or perhaps
|
||||
only finalized) later. If you need both Java inheritance and
|
||||
native resources, you should consider moving the native state to
|
||||
a separate class, and only keep a reference to objects of that
|
||||
class. This way, cloning and serialization issues can be
|
||||
avoided in most cases.
|
||||
|
||||
If there are native resources associated with an object, the
|
||||
class should have an explicit resource deallocation method
|
||||
(<<sect-Defensive_Coding-Java-Language-Resources>>) and a
|
||||
finalizer (<<sect-Defensive_Coding-Java-Language-Finalizers>>) as a
|
||||
last resort. The need for finalization means that a minimum
|
||||
amount of synchronization is needed. Code on the native side
|
||||
should check that the object is not in a closed/freed state.
|
||||
|
||||
Many JNI functions create local references. By default, these
|
||||
persist until the JNI-implemented method returns. If you create
|
||||
many such references (e.g., in a loop), you may have to free
|
||||
them using `DeleteLocalRef`, or start using
|
||||
`PushLocalFrame` and
|
||||
`PopLocalFrame`. Global references must be
|
||||
deallocated with `DeleteGlobalRef`, otherwise
|
||||
there will be a memory leak, just as with
|
||||
`malloc` and `free`.
|
||||
|
||||
When throwing exceptions using `Throw` or
|
||||
`ThrowNew`, be aware that these functions
|
||||
return regularly. You have to return control manually to the
|
||||
JVM.
|
||||
|
||||
Technically, the `JNIEnv` pointer is not
|
||||
necessarily constant during the lifetime of your JNI module.
|
||||
Storing it in a global variable is therefore incorrect.
|
||||
Particularly if you are dealing with callbacks, you may have to
|
||||
store the pointer in a thread-local variable (defined with
|
||||
`__thread`). It is, however, best to avoid the
|
||||
complexity of calling back into Java code.
|
||||
|
||||
Keep in mind that C/C++ and Java are different languages,
|
||||
despite very similar syntax for expressions. The Java memory
|
||||
model is much more strict than the C or C++ memory models, and
|
||||
native code needs more synchronization, usually using JVM
|
||||
facilities or POSIX threads mutexes. Integer overflow in Java
|
||||
is defined, but in C/C++ it is not (for the
|
||||
`jint` and `jlong` types).
|
||||
|
||||
[[sect-Defensive_Coding-Java-MiscUnsafe]]
|
||||
===== `sun.misc.Unsafe`
|
||||
|
||||
The `sun.misc.Unsafe` class is unportable and
|
||||
contains many functions explicitly designed to break Java memory
|
||||
safety (for performance and debugging). If possible, avoid
|
||||
using this class.
|
Loading…
Add table
Add a link
Reference in a new issue