This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 458170e75967373354e76f97dcfed1d974605e4e
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Tue Jul 2 17:43:24 2013 +0200
Add a chapter on Java
---
defensive-coding/en-US/Defensive_Coding.xml | 1 +
defensive-coding/en-US/Java/Java.xml | 10 +
defensive-coding/en-US/Java/Language.xml | 258 +++++++++++++++++++++
defensive-coding/en-US/Java/LowLevel.xml | 157 +++++++++++++
defensive-coding/en-US/Java/schemas.xml | 5 +
defensive-coding/en-US/Java/snippets/Finally.xml | 12 +
.../en-US/Java/snippets/JNI-Pointers.xml | 36 +++
.../en-US/Java/snippets/TryWithResource.xml | 9 +
defensive-coding/src/Java-JNI-Pointers.c | 41 ++++
defensive-coding/src/JavaFinally.java | 31 +++
defensive-coding/src/src.mk | 9 +-
11 files changed, 568 insertions(+), 1 deletion(-)
diff --git a/defensive-coding/en-US/Defensive_Coding.xml
b/defensive-coding/en-US/Defensive_Coding.xml
index cef4bbf..eb6e763 100644
--- a/defensive-coding/en-US/Defensive_Coding.xml
+++ b/defensive-coding/en-US/Defensive_Coding.xml
@@ -6,6 +6,7 @@
<title>Programming Languages</title>
<xi:include href="C/C.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="CXX/CXX.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Java/Java.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="Python/Language.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
<part>
diff --git a/defensive-coding/en-US/Java/Java.xml b/defensive-coding/en-US/Java/Java.xml
new file mode 100644
index 0000000..7c5700c
--- /dev/null
+++ b/defensive-coding/en-US/Java/Java.xml
@@ -0,0 +1,10 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<chapter id="chap-Defensive_Coding-Java">
+ <title>The Java Programming Language</title>
+
+ <xi:include href="Language.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="LowLevel.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+</chapter>
+
diff --git a/defensive-coding/en-US/Java/Language.xml
b/defensive-coding/en-US/Java/Language.xml
new file mode 100644
index 0000000..edea9a4
--- /dev/null
+++ b/defensive-coding/en-US/Java/Language.xml
@@ -0,0 +1,258 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<section id="sect-Defensive_Coding-Java-Language">
+ <title>The core language</title>
+ <para>
+ Implementations of the Java programming language provide strong
+ memory safety, even in the presence of data races in concurrent
+ code. This prevents a large range of security vulnerabilities
+ from occurring, unless certain low-level features are used; see
+ <xref linkend="sect-Defensive_Coding-Java-LowLevel"/>.
+ </para>
+
+ <section id="sect-Defensive_Coding-Java-Language-Resources">
+ <title>Resource management</title>
+ <para>
+ Unlike C++, Java does not offer destructors which can deallocate
+ resources in a predictable fashion. All resource management has
+ to be manual, at the usage site. (Finalizers are generally not
+ usable for resource management, especially in high-performance
+ code; see <xref
+ linkend="sect-Defensive_Coding-Java-Language-Finalizers"/>.)
+ </para>
+ <para>
+ The first option is the
+ <literal>try</literal>-<literal>finally</literal>
construct, as
+ shown in <xref
linkend="ex-Defensive_Coding-Java-Language-Finally"/>.
+ The code in the <literal>finally</literal> block should be as short as
+ possible and should not throw any exceptions.
+ </para>
+ <example id="ex-Defensive_Coding-Java-Language-Finally">
+ <title>Resource management with a
+ <literal>try</literal>-<literal>finally</literal>
block</title>
+ <xi:include href="snippets/Finally.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ Note that the resource allocation happens
+ <emphasis>outside</emphasis> the <literal>try</literal>
block,
+ and that there is no <literal>null</literal> check in the
+ <literal>finally</literal> block. (Both are common artifacts
+ stemming from IDE code templates.)
+ </para>
+ <para>
+ If the resource object is created freshly and implements the
+ <literal>java.lang.AutoCloseable</literal> interface, the code
+ in <xref
+ linkend="ex-Defensive_Coding-Java-Language-TryWithResource"/> can be
+ used instead. The Java compiler will automatically insert the
+ <function>close()</function> method call in a synthetic
+ <literal>finally</literal> block.
+ </para>
+ <example id="ex-Defensive_Coding-Java-Language-TryWithResource">
+ <title>Resource management using the
+ <literal>try</literal>-with-resource construct</title>
+ <xi:include href="snippets/TryWithResource.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ To be compatible with the <literal>try</literal>-with-resource
+ construct, new classes should name the resource deallocation
+ method <function>close()</function>, and implement the
+ <literal>AutoCloseable</literal> interface (the latter breaking
+ backwards compatibility with Java 6). However, using the
+ <literal>try</literal>-with-resource construct with objects that
+ are not freshly allocated is at best awkward, and an explicit
+ <literal>finally</literal> block is usually the better approach.
+ </para>
+ <para>
+ In general, it is best to design the programming interface in
+ such a way that resource deallocation methods like
+ <function>close()</function> cannot throw any (checked or
+ unchecked) exceptions, but this should not be a reason to ignore
+ any actual error conditions.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-Language-Finalizers">
+ <title>Finalizers</title>
+ <para>
+ Finalizers can be used a last-resort approach to free resources
+ which would otherwise leak. Finalization is unpredictable,
+ costly, and there can be a considerable delay between the last
+ reference to an object going away and the execution of the
+ finalizer. Generally, manual resource management is required;
+ see <xref
linkend="sect-Defensive_Coding-Java-Language-Resources"/>.
+ </para>
+ <para>
+ Finalizers should be very short and should only deallocate
+ native or other external resources held directly by the object
+ being finalized. In general, they must use synchronization:
+ Finalization necessarily happens on a separate thread because it is
+ inherently concurrent. There can be multiple finalization
+ threads, and despite each object being finalized at most once,
+ the finalizer must not assume that it has exclusive access to
+ the object being finalized (in the <literal>this</literal>
+ pointer).
+ </para>
+ <para>
+ Finalizers should not deallocate resources held by other
+ objects, especially if those objects have finalizers on their
+ own. In particular, it is a very bad idea to define a finalizer
+ just to invoke the resource deallocation method of another object,
+ or overwrite some pointer fields.
+ </para>
+ <para>
+ Finalizers are not guaranteed to run at all. For instance, the
+ virtual machine (or the machine underneath) might crash,
+ preventing their execution.
+ </para>
+ <para>
+ Objects with finalizers are garbage-collected much later than
+ objects without them, so using finalizers to zero out key
+ material (to reduce its undecrypted lifetime in memory) may have
+ the opposite effect, keeping objects around for much longer and
+ prevent them from being overwritten in the normal course of
+ program execution.
+ </para>
+ <para>
+ For the same reason, code which allocates objects with
+ finalizers at a high rate will eventually fail (likely with a
+ <literal>java.lang.OutOfMemoryError</literal> exception) because
+ the virtual machine has finite resources for keeping track of
+ objects pending finalization. To deal with that, it may be
+ necessary to recycle objects with finalizers.
+ </para>
+ <para>
+ The remarks in this section apply to finalizers which are
+ implemented by overriding the <function>finalize()</function>
+ method, and to custom finalization using reference queues.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-Language-Exceptions">
+ <title>Recovering from exceptions and errors</title>
+ <para>
+ Java exceptions come in three kinds, all ultimately deriving
+ from <literal>java.lang.Throwable</literal>:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Run-time exceptions</emphasis> do not have to be
+ declared explicitly and can be explicitly thrown from any
+ code, by calling code which throws them, or by triggering an
+ error condition at run time, like division by zero, or an
+ attempt at an out-of-bounds array access. These exceptions
+ derive from from the
+ <literal>java.lang.RuntimeException</literal> class (perhaps
+ indirectly).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Checked exceptions</emphasis> have to be declared
+ explicitly by functions that throw or propagate them. They
+ are similar to run-time exceptions in other regards, except
+ that there is no language construct to throw them (except
+ the <literal>throw</literal> statement itself). Checked
+ exceptions are only present at the Java language level and
+ are only enforced at compile time. At run time, the virtual
+ machine does not know about them and permits throwing
+ exceptions from any code. Checked exceptions must derive
+ (perhaps indirectly) from the
+ <literal>java.lang.Exception</literal> class, but not from
+ <literal>java.lang.RuntimeException</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Errors</emphasis> are exceptions which typically
+ reflect serious error conditions. They can be thrown at any
+ point in the program, and do not have to be declared (unlike
+ checked exceptions). In general, it is not possible to
+ recover from such errors; more on that below, in <xref
+ linkend="sect-Defensive_Coding-Java-Language-Exceptions-Errors"/>.
+ Error classes derive (perhaps indirectly) from
+ <literal>java.lang.Error</literal>, or from
+ <literal>java.lang.Throwable</literal>, but not from
+ <literal>java.lang.Exception</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The general expection is that run-time errors are avoided by
+ careful programming (e.g., not dividing by zero). Checked
+ exception are expected to be caught as they happen (e.g., when
+ an input file is unexpectedly missing). Errors are impossible
+ to predict and can happen at any point and reflect that
+ something went wrong beyond all expectations.
+ </para>
+
+ <section id="sect-Defensive_Coding-Java-Language-Exceptions-Errors">
+ <title>The difficulty of catching errors</title>
+ <para>
+ Errors (that is, exceptions which do not (indirectly) derive
+ from <literal>java.lang.Exception</literal>), have the
+ peculiar property that catching them is problematic. There
+ are several reasons for this:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ The error reflects a failed consistenty check, for example,
+ <literal>java.lang.AssertionError</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The error can happen at any point, resulting in
+ inconsistencies due to half-updated objects. Examples are
+ <literal>java.lang.ThreadDeath</literal>,
+ <literal>java.lang.OutOfMemoryError</literal> and
+ <literal>java.lang.StackOverflowError</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The error indicates that virtual machine failed to provide
+ some semantic guarantees by the Java programming language.
+ <literal>java.lang.ExceptionInInitializerError</literal>
+ is an example—it can leave behind a half-initialized
+ class.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ In general, if an error is thrown, the virtual machine should
+ be restarted as soon as possible because it is in an
+ inconsistent state. Continuing running as before can have
+ unexpected consequences. However, there are legitimate
+ reasons for catching errors because not doing so leads to even
+ greater problems.
+ </para>
+ <para>
+ It is usually necessary to log errors. Otherwise, no trace of
+ the problem might be left anywhere, making it very difficult
+ to diagnose realted failures. Consequently, if you catch
+ <literal>java.lang.Exception</literal> to log and suppress all
+ unexpected exceptions (for example, in a request dispatching
+ loop), you should consider switching to
+ <literal>java.lang.Throwable</literal> instead, to also cover
+ errors.
+ </para>
+ <para>
+ The other reason mainly applies to such request dispatching
+ loops: If you do not catch errors, the loop stops looping,
+ resulting in a denial of service.
+ </para>
+ <para>
+ However, if possible, catching errors should be coupled with a
+ way to signal the requirement of a virtual machine restart.
+ </para>
+ </section>
+ </section>
+</section>
+
diff --git a/defensive-coding/en-US/Java/LowLevel.xml
b/defensive-coding/en-US/Java/LowLevel.xml
new file mode 100644
index 0000000..18ba1ad
--- /dev/null
+++ b/defensive-coding/en-US/Java/LowLevel.xml
@@ -0,0 +1,157 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<section id="sect-Defensive_Coding-Java-LowLevel">
+ <title>Low-level features of the virtual machine</title>
+
+ <section id="sect-Defensive_Coding-Java-Reflection">
+ <title><literal>Reflection and private
parts</literal></title>
+ <para>
+ The <function>setAccessible(boolean)</function> method of the
+ <literal>java.lang.reflect.AccessibleObject</literal> 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
+ <literal>java.lang.reflect.Constructor</literal>,
+ <literal>java.lang.reflect.Method</literal>, or
+ <literal>java.lang.reflect.Field</literal> 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
+ <function>setAccessible(boolean)</function> method, this should
+ not happen because all the language-defined checks still apply.)
+ </para>
+ <para>
+ This feature should be avoided if possible.
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-JNI">
+ <title>Java Native Interface (JNI)</title>
+ <para>
+ The Java Native Interface allows calling from Java code
+ functions specifically written for this purpose, usually in C or
+ C++.
+ </para>
+ <para>
+ 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.
+ </para>
+ <para>
+ To provide a moderate amount of type safety, it is recommended
+ to recreate the class-specific header file using
+ <application>javah</application> during the build process,
+ include it in the implementation, and use the
+ <option>-Wmissing-declarations</option> option.
+ </para>
+ <para>
+ 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).
+ </para>
+ <para>
+ When using <function>GetPrimitiveArrayCritical</function> or
+ <function>GetStringCritical</function>, 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.
+ </para>
+ <para>
+ If necessary, you can use the Java <literal>long</literal> type
+ to store a C pointer in a field of a Java class. On the C side,
+ when casting between the <literal>jlong</literal> value and the
+ pointer on the C side,
+ </para>
+ <para>
+ You should not try to perform pointer arithmetic on the Java
+ side (that is, you should treat pointer-carrying
+ <literal>long</literal> 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.
+ </para>
+ <example id="ex-Defensive_Coding-Java-JNI-Pointers">
+ <title>Array length checking in JNI code</title>
+ <xi:include href="snippets/JNI-Pointers.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ </example>
+ <para>
+ In any case, classes referring to native resources must be
+ declared <literal>final</literal>, 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.
+ </para>
+ <para>
+ If there are native resources associated with an object, the
+ class should have an explicit resource deallocation method
+ (<xref
+ linkend="sect-Defensive_Coding-Java-Language-Resources"/>) and a
+ finalizer (<xref
+ linkend="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.
+ </para>
+ <para>
+ 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 <function>DeleteLocalRef</function>, or start using
+ <function>PushLocalFrame</function> and
+ <function>PopLocalFrame</function>. Global references must be
+ deallocated with <function>DeleteGlobalRef</function>, otherwise
+ there will be a memory leak, just as with
+ <function>malloc</function> and <function>free</function>.
+ </para>
+ <para>
+ When throwing exceptions using <function>Throw</function> or
+ <function>ThrowNew</function>, be aware that these functions
+ return regularly. You have to return control manually to the
+ JVM.
+ </para>
+ <para>
+ Technically, the <literal>JNIEnv</literal> 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
+ <literal>__thread</literal>). It is, however, best to avoid the
+ complexity of calling back into Java code.
+ </para>
+ <para>
+ 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
+ <literal>jint</literal> and <literal>jlong</literal>
types).
+ </para>
+ </section>
+
+ <section id="sect-Defensive_Coding-Java-MiscUnsafe">
+ <title><literal>sun.misc.Unsafe</literal></title>
+ <para>
+ The <literal>sun.misc.Unsafe</literal> class is unportable and
+ contains many functions explicitly designed to break Java memory
+ safety (for performance and debugging). If possible, avoid
+ using this class.
+ </para>
+ </section>
+
+</section>
diff --git a/defensive-coding/en-US/Java/schemas.xml
b/defensive-coding/en-US/Java/schemas.xml
new file mode 100644
index 0000000..b18bd04
--- /dev/null
+++ b/defensive-coding/en-US/Java/schemas.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<locatingRules
xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+ <uri resource="Language.xml"
uri="../../docbook-schema/docbook.rnc"/>
+ <uri resource="LowLevel.xml"
uri="../../docbook-schema/docbook.rnc"/>
+</locatingRules>
diff --git a/defensive-coding/en-US/Java/snippets/Finally.xml
b/defensive-coding/en-US/Java/snippets/Finally.xml
new file mode 100644
index 0000000..b32ec36
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/Finally.xml
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+InputStream in = new BufferedInputStream(new FileInputStream(path));
+try {
+ readFile(in);
+} finally {
+ in.close();
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml
b/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml
new file mode 100644
index 0000000..95d386e
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/JNI-Pointers.xml
@@ -0,0 +1,36 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *jEnv, jclass clazz, jbyteArray buffer, jint offset, jint length)
+{
+ assert(sizeof(jint) == sizeof(unsigned));
+ if (offset < 0 || length < 0) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "negative offset/length");
+ return 0;
+ }
+ unsigned uoffset = offset;
+ unsigned ulength = length;
+ // This cannot overflow because of the check above.
+ unsigned totallength = uoffset + ulength;
+ unsigned actuallength = (*jEnv)->GetArrayLength(jEnv, buffer);
+ if (totallength > actuallength) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "offset + length too large");
+ return 0;
+ }
+ unsigned char *ptr = (*jEnv)->GetPrimitiveArrayCritical(jEnv, buffer, 0);
+ if (ptr == NULL) {
+ return 0;
+ }
+ unsigned long long sum = 0;
+ for (unsigned char *p = ptr + uoffset, *end = p + ulength; p != end; ++p) {
+ sum += *p;
+ }
+ (*jEnv)->ReleasePrimitiveArrayCritical(jEnv, buffer, ptr, 0);
+ return sum;
+}
+</programlisting>
diff --git a/defensive-coding/en-US/Java/snippets/TryWithResource.xml
b/defensive-coding/en-US/Java/snippets/TryWithResource.xml
new file mode 100644
index 0000000..a9f13f6
--- /dev/null
+++ b/defensive-coding/en-US/Java/snippets/TryWithResource.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="Java">
+try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
+ readFile(in);
+}
+</programlisting>
diff --git a/defensive-coding/src/Java-JNI-Pointers.c
b/defensive-coding/src/Java-JNI-Pointers.c
new file mode 100644
index 0000000..c9108a6
--- /dev/null
+++ b/defensive-coding/src/Java-JNI-Pointers.c
@@ -0,0 +1,41 @@
+#include <jni.h>
+
+#include <assert.h>
+
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *, jclass, jbyteArray, jint, jint);
+
+static jclass arrayIndexOutOfBoundsExceptionClass;
+
+//+ Java JNI-Pointers
+JNIEXPORT jint JNICALL Java_sum
+ (JNIEnv *jEnv, jclass clazz, jbyteArray buffer, jint offset, jint length)
+{
+ assert(sizeof(jint) == sizeof(unsigned));
+ if (offset < 0 || length < 0) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "negative offset/length");
+ return 0;
+ }
+ unsigned uoffset = offset;
+ unsigned ulength = length;
+ // This cannot overflow because of the check above.
+ unsigned totallength = uoffset + ulength;
+ unsigned actuallength = (*jEnv)->GetArrayLength(jEnv, buffer);
+ if (totallength > actuallength) {
+ (*jEnv)->ThrowNew(jEnv, arrayIndexOutOfBoundsExceptionClass,
+ "offset + length too large");
+ return 0;
+ }
+ unsigned char *ptr = (*jEnv)->GetPrimitiveArrayCritical(jEnv, buffer, 0);
+ if (ptr == NULL) {
+ return 0;
+ }
+ unsigned long long sum = 0;
+ for (unsigned char *p = ptr + uoffset, *end = p + ulength; p != end; ++p) {
+ sum += *p;
+ }
+ (*jEnv)->ReleasePrimitiveArrayCritical(jEnv, buffer, ptr, 0);
+ return sum;
+}
+//-
diff --git a/defensive-coding/src/JavaFinally.java
b/defensive-coding/src/JavaFinally.java
new file mode 100644
index 0000000..7c0fe54
--- /dev/null
+++ b/defensive-coding/src/JavaFinally.java
@@ -0,0 +1,31 @@
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+public abstract class JavaFinally {
+ File path;
+
+ abstract void readFile(InputStream in) throws Exception;
+
+ void finallyExample() throws Exception {
+ //+ Java Finally
+ InputStream in = new BufferedInputStream(new FileInputStream(path));
+ try {
+ readFile(in);
+ } finally {
+ in.close();
+ }
+ //-
+ }
+
+ void tryWithResource() throws Exception {
+ //+ Java TryWithResource
+ try (InputStream in = new BufferedInputStream(new FileInputStream(path))) {
+ readFile(in);
+ }
+ //-
+ }
+
+ static native int sum(byte[] buffer, int offset, int length);
+}
diff --git a/defensive-coding/src/src.mk b/defensive-coding/src/src.mk
index f2eac6f..1bd5f45 100644
--- a/defensive-coding/src/src.mk
+++ b/defensive-coding/src/src.mk
@@ -13,8 +13,15 @@ compile_only += C-Pointers-remaining
compile_only += C-Arithmetic-add
compile_only += C-Arithmetic-mult
+compile_only += Java-JNI-Pointers
+CFLAGS_Java-JNI-Pointers = \
+ -I/usr/lib/jvm/java/include -I/usr/lib/jvm/java/include/linux
+
# List Java files which sould be compiled
+compile_java += JavaFinally
+
compile_java += TLSClientOpenJDK
+JCFLAGS_TLSClientOpenJDK = -source 1.6 -target 1.6
# List fiels which will be compiled and linked, together with
# additional dependencies.
@@ -52,7 +59,7 @@ src/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) $(DEFINES) $(CFLAGS_$(basename $(notdir $@))) -c $< -o $@
src/%.class: src/%.java
- javac -source 1.6 -target 1.6 -Xlint:all $^
+ javac $(JCFLAGS_$(basename $(notdir $@))) -Xlint:all $^
src/%: src/%.o
$(CXX) $(LDFLAGS) $^ -o $@ $(LIBS_$(notdir $@))
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.