The Java software platform provides a number of features designed for improving the security of Java applications. This includes enforcing runtime constraints through the use of the Java Virtual Machine (JVM), a security manager that sandboxes untrusted code from the rest of the operating system, and a suite of security APIs that Java developers can utilise. Despite this, criticism has been directed at the programming language, and Oracle, due to an increase in malicious programs that revealed security vulnerabilities in the JVM, which were subsequently not properly addressed by Oracle in a timely manner.

Security features The JVM The binary form of programs running on the Java platform is not native machine code but an intermediate bytecode. The JVM performs verification on this bytecode before running it to prevent the program from performing unsafe operations such as branching to incorrect locations, which may contain data rather than instructions. It also allows the JVM to enforce runtime constraints such as array bounds checking. This means that Java programs are significantly less likely to suffer from memory safety flaws such as buffer overflow than programs written in languages such as C which do not provide such memory safety guarantees.

The platform does not allow programs to perform certain potentially unsafe operations such as pointer arithmetic or unchecked type casts. It manages memory allocation and initialization and provides automatic garbage collection which in many cases (but not all) relieves the developer from manual memory management. This contributes to type safety and memory safety.

Security manager The platform provides a security manager which allows users to run untrusted bytecode in a "sandboxed" environment designed to protect them from malicious or poorly written software by preventing the untrusted code from accessing certain platform features and APIs. For example, untrusted code might be prevented from reading or writing files on the local filesystem, running arbitrary commands with the current user's privileges, accessing communication networks, accessing the internal private state of objects using reflection, or causing the JVM to exit.

The security manager also allows Java programs to be cryptographically signed; users can choose to allow code with a valid digital signature from a trusted entity to run with full privileges in circumstances where it would otherwise be untrusted.

Users can also set fine-grained access control policies for programs from different sources. For example, a user may decide that only system classes should be fully trusted, that code from certain trusted entities may be allowed to read certain specific files, and that all other code should be fully sandboxed.

Security APIs The Java Class Library provides a number of APIs related to security, such as standard cryptographic algorithms, authentication, and secure communication protocols.

The class sun.misc.Unsafe is an internal utility class in the Java programming language which is a collection of low-level unsafe operations. While it is not a part of the official Java Class Library, it is called internally by the Java libraries. It resides in an unofficial Java module named jdk.unsupported. Beginning in Java 11, it has been partially migrated to jdk.internal.misc.Unsafe (which resides in module java.base).

Its primary feature is to allow direct memory management (similar to C memory management) and memory address manipulation, manipulating objects and fields, thread manipulation, and concurrency primitives.

It is final, and is a singleton class with a private constructor.

It contains the following methods, almost all of which invoke Java Native Interface: : retrieves the Unsafe instance. It uses sun.reflect.Reflection to do so. : fetches a value (a field or array element) in the object at the given offset. (There are corresponding getBoolean(), getByte(), getShort(), getChar(), getLong(), getFloat(), and getDouble() methods as well.) : stores a value into an object at the given offset. (There are corresponding putBoolean(), putByte(), putShort(), putChar(), putLong(), putFloat(), and putDouble() methods as well.) : fetches a reference value from an object at the given offset. : stores a reference value into an object at the given offset. : fetches a value at the given address. (There are corresponding getBoolean(), getByte(), getShort(), getChar(), getLong(), getFloat(), and getDouble() methods as well.) : stores a value into the given address. (There are corresponding putBoolean(), putByte(), putShort(), putChar(), putLong(), putFloat(), and putDouble() methods as well.) : fetches a native pointer from a given address. : stores a native pointer into a given address. : allocates a block of native memory of the given size (similar to ). : resizes a block of native memory to the given size (similar to ). , : sets all bytes in a block of memory to a fixed value (similar to ). , : sets all bytes in a given block of memory to a copy of another block (similar to ). : deallocates a block of native memory obtained from allocateMemory() or reallocateMemory(), similar to ). : obtains the location of a given field in the storage allocation of its class. : obtains the location of a given static field in conjunction with staticFieldBase(). : obtains the location of a given static field in conjunction with staticFieldOffset(). : ensures the given class has been initialized. : obtains the offset of the first element in the storage allocation of a given array class. : obtains the scale factor for addressing elements in the storage allocation of a given array class. : obtains the size (in bytes) of a native pointer. : obtains the size (in bytes) of a native memory page. : signals to the JVM to define a class without security checks. : signals to the JVM to define a class but do not make it known to the class loader or system directory. : allocates an instance of a class without running its constructor. : locks an object. : unlocks an object. : tries to lock an object, returning whether the lock succeeded. : throws an exception without telling the verifier. : updates a variable to x if it is holding expected, returning whether the operation succeeded. (There are corresponding compareAndSwapLong() and compareAndSwapObject() methods as well.) : volatile version of getInt(). (There are corresponding getBooleanVolatile(), getByteVolatile(), getShortVolatile(), getCharVolatile(), getLongVolatile(), getFloatVolatile(), getDoubleVolatile(), and getObjectVolatile() methods as well.) : volatile version of putInt(). (There are corresponding putBooleanVolatile(), putByteVolatile(), putShortVolatile(), putCharVolatile(), putLongVolatile(), putFloatVolatile(), putDoubleVolatile(), and putObjectVolatile() methods as well.) : version of putIntVolatile() not guaranteeing immediate visibility of storage to other threads. (There are corresponding putOrderedLong() and putOrderedObject() methods as well.) : unblocks a thread. : blocks the current thread. : gets the load average in the system run queue assigned to available processors averaged over various periods of time. : invokes the given direct byte buffer's cleaner. : ensures loads and stores before the fence will not be reordered with loads and stores after the fence. : ensures loads before the fence will not be reordered with loads and stores after the fence. : ensures loads and stores before the fence will not be reordered with stores after the fence.

Examples An example usage the following: package org.wikipedia.examples;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class Example { public static void main(String[] args) throws Exception { // Get Unsafe instance via reflection Field f = Unsafe.class.getDeclaredField("theUnsafe"); f.setAccessible(true); Unsafe unsafe = (Unsafe)f.get(null);

// Allocate a block of 8 bytes long memoryAddress = unsafe.allocateMemory(8L);

try { // Insert a long into the memory, and read from that block unsafe.putLong(memoryAddress, 123456789L); long value = unsafe.getLong(memoryAddress); System.out.printf("Value from memory: %d%n", value); // Output: 123456789 } finally { // Free the allocated memory unsafe.freeMemory(memoryAddress);

One can also wrap native memory segments, like java.lang.foreign.MemorySegment: package org.wikipedia.examples;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class NativeMemory implements AutoCloseable { private static final Unsafe unsafe; private final long address; private final long size;

static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = (Unsafe)theUnsafe.get(null); } catch (Exception e) { throw new RuntimeException("Unable to access Unsafe", e);

public NativeMemory(long size) { this.size = size; this.address = unsafe.allocateMemory(size);

public void putByte(long offset, byte value) { checkBounds(offset, 1); unsafe.putByte(address + offset, value);

public byte getByte(long offset) { checkBounds(offset, 1); return unsafe.getByte(address + offset);

private void checkBounds(long offset, long bytes) { if (offset < 0 || offset + bytes > size) { throw new IndexOutOfBoundsException(String.format("Offset out of bounds: %d", offset));

@Override public void close() { unsafe.freeMemory(address);

In use: package org.wikipedia.examples;

public class Main { public static void main(String[] args) { try (NativeMemory mem = new NativeMemory(1024)) { mem.putByte(0, (byte)42); System.out.printf("Value: %s%n", mem.getByte(0));

Potential sources of security vulnerabilities in Java applications

There are a number of possible sources of security vulnerabilities in Java applications, some of which are common to non-Java applications and some of which are specific to the Java platform. (Note that these refer to potential sources of vulnerabilities which need to be kept in mind by security-conscious programmers: this is not intended as a list of actual vulnerabilities.)

Examples of potential sources of vulnerability common to Java and non-Java applications are:

Vulnerabilities in the protection mechanisms provided by the hardware or operating system which the application relies upon for its security Vulnerabilities in native libraries, such as the C standard library, which may be used to implement the application and/or runtime Vulnerabilities caused purely by errors in user programs (for example improper construction of SQL queries leading to SQL injection vulnerabilities)

However, much discussion of Java security focusses on potential sources of vulnerability specific to the Java platform. These include:

Vulnerabilities in the sandboxing mechanism which allow untrusted bytecode to circumvent the restrictions imposed by the security manager Vulnerabilities in the Java class library which an application relies upon for its security

A vulnerability in the Java platform will not necessarily make all Java applications vulnerable. When vulnerabilities and patches are announced, for example by Oracle, the announcement will normally contain a breakdown of which types of application are affected (example).