Friday, October 28, 2022

Curly Braces #5: Null is not nothing

Oracle Java, Oracle Java Exam, Oracle Java Career, Oracle Java Skills, Oracle Java Jobs, Oracle Java Preparation, Oracle Java Tutorial and Materials


What is null? There’s no easy answer. If this essay were an episode of Seinfeld, it would be called “The Null Column,” because it’s a column about nothing—literally. Upon further inspection, however, null is not nothing. That’s what void is for. In fact, void is a much clearer concept than null. void is pure. void is simple. void is loyal and unwavering. But void is not null. If null were on Facebook, its relationship status would be “it’s complicated” (see Figure 1).

Oracle Java, Oracle Java Exam, Oracle Java Career, Oracle Java Skills, Oracle Java Jobs, Oracle Java Preparation, Oracle Java Tutorial and Materials
Figure 1. Null is a complicated concept.

In the excellent book Zero: The Biography of a Dangerous Idea, which I highly recommend, Charles Seife describes zero as a once-evil concept that was missing from ancient number systems. The idea of zero or nothingness (sounds like null to me) is one of the greatest paradoxes of human thought, according to the author. Its invention and acceptance led to other great discoveries such as fractions and even calculus.

On UNIX, null can be a device, as in /dev/null, where it acts like a black hole when written to; nothing ever comes out. This contrasts with a null modem cable, where all the data certainly does come out; it’s just crossed over electrically.

In common vernacular, some things can be “null and void” at the same time, such as a clause in a contract, a discount offer used on the wrong day or for the wrong person. But that concept never applies in a programming language: There, nothing is both null and void.

Maybe null was best explained in my favorite movie, Tron, During a scene with the evil Sark and one of his underlings, in a fit of anger and disappointment, Sark calls the errant program “Null Unit.” By this, Sark implies emptiness, absence of intelligence, disappointment, or just plain frustration.

Looking back, I started programming at a young age with TI-BASIC, then Commodore BASIC, and then 68000 Assembly for my Amiga (I couldn’t afford a C compiler at the time). None of those has the concept of null. But it was there in spirit because null is a notion, a concept, an abstraction. It’s like love: You cannot precisely define it, but you know it when you have it. Heck, like love, null even causes a feeling, such as that sinking feeling you get when your program crashes from a null pointer (I mean a null reference).

The polyglot null


For programming languages, null means different things depending on the language, and there are different sets of rules that govern how it’s used. For instance, in C, null is zero. Even Brian Kernighan and Dennis Ritchie’s The C Programming Language uses 0 in place of null (well, NULL) in some code examples.

char* alloc(int n) {
    if ( allocbuf + ALLOCSIZE - allocp >= n ) {
        allocp += n;
        return allocp - n;
    } else /* no room */
        return 0;
}

Null is simply defined as zero in a macro.

#define NULL 0

In C, null is also confused with false. The following code compiles:

bool b = false;
int y = 0;
if ( !b && !y ) {
    return 1;
}
return 0;

The snippet above outputs the following:

RUN FINISHED; exit value 1

Perhaps it’s a null pointer constant? Even this C code compiles.

int main(int argc, char** argv) {
    int* p = 0;
    int  q = NULL;
    return q;
}

Yes, the above code may generate a warning, but when it runs, the program exits with the value zero.

RUN FINISHED; exit value 0;

That’s confusing!

In JavaScript, null is null. In fact, you can call it NULL, or Null, or Nil, but don’t call it undefined. That’s an entirely different thing unless you’re checking with == (double equals signs) instead of === (triple equals signs). In this context, let’s simply call null “null-ish.”

Python looks promising, as it uses None to denote null, which at first makes sense. Yet when you see how None behaves, you realize it, too, will let you down. For example, setting a function return to None does what you’d expect: It returns nothing. But if you print the value of a function that returns None, you get the following:

>>> eric=None
>>> print(eric)
None

In Python, printing the value None gives you something, in the form of text that spells out the word None. That’s irony at the level of genius.

What about Java?


Surely Java gets null right, right? Of course, in Java, null is a null reference—except when null is a null pointer.

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "Object.toString()" because "ref" is null
     com.ericbruno.nullreference.Test.main(Test.java:11)

Nevertheless, null means something in Java. It’s not void. If your method is defined with a void return, you can’t return anything. Yet if your method is declared to return an Object, you can never return void, but you sure can return null. (You can also return an actual Object, if you want to be boring.)

And I recently learned from Bruce Eckel that null can even be a legitimate case in a Java switch statement.

More precisely, null is not a Java keyword, but instead it is a literal in Java.

According to the Java Language Specification, a literal is a representation of a primitive type, a String type, or the null type.

As the specification states, the null type has one value: the null reference, represented by the literal null. The null type, in contrast, is nameless. As you likely know already, the null literal can be assigned only to reference types, not to primitive types. Although you can cast a null reference to any reference type in Java, the return from instanceof is always false, meaning null is null in Java.

public class Test {
    public static void main(String[] args) {
        Integer i = (Integer)null;
        if ( i instanceof Integer ) {
            System.out.println("i is of type Integer");
        }
    }
}

The result of the code above is no output. Take that, Python!

Source: oracle.com

Friday, October 21, 2022

Curly Braces #4: Network data transmission and compression in Java


I find that writing messaging middleware allows me to build robust distributed enterprise software systems. Once I even built my own Java Message Service (JMS) implementation and learned a lot about Java network I/O and related performance.

One important lesson I learned is high-performance messaging software requires more than fast, efficient code. You also need a strong fundamental understanding of networking—and knowledge about the I/O limitations of the systems you run on. For example, when data is transmitted between distributed components, there comes a point where even the fastest code waits on network I/O—what’s called being I/O bound. Figure 1 shows what I mean.

Oracle Java, Java Exam, Java Exam Prep, Java Tutorial and Material, Java Guides, Java Certification, Java Prep, Java Preparation, Java Learning

Figure 1. An I/O-bound thread

Before getting into data compression as one possible solution to addressing I/O delays, I’ll review some basics of Java network programming.

Java network programming


The foundation for Java networking is the combination of the java.net.Socket and java.net.ServerSocket classes. In short, Socket is for client code, while ServerSocket is for servers, which clients connect to.

As with most Java I/O programming, data is exchanged through a combination of the java.io.InputStream and java.io.OutputStream classes. Note that the use of server and client classes doesn’t dictate data direction. A Java server application can sit and listen for a client to send it data after connecting, or the server can serve data to a client that just listens. And of course, data can flow both ways between the two in a request and response paradigm, as with a web browser and server.

Here is a sample implementation of ServerSocket that waits for a client to connect. A client can be any application, regardless of implementation language, that connects to the correct IP address and port.

try {
        ServerSocket clientConnect = new ServerSocket(8080);
        Socket client = clientConnect.accept(); // blocking call!
        InputStream instream = client.getInputStream();
        DataInputStream dis = new DataInputStream( instream );
        while ( true ) {
            String msg = dis.readUTF();
            System.out.println("Message: " + msg);
        }
    }
    catch ( Exception e ) {
        e.printStackTrace();
    }

The code above creates a ServerSocket that listens on port 8080 on the host it runs on. The call to accept() blocks and waits until a network client connects on the listening port, at which point a Socket connection to the client is returned.

In this implementation, the server listens for String messages and outputs them to the command line. To do this, the client’s InputStream is passed to the DataInputStream constructor to instantiate a listener. The subsequent call to readUTF blocks until a String message arrives in its entirety.

Here’s the simplified client code that connects to the server and sends a String message.

try {
        Socket sender = new Socket("localhost", 8080);
        if ( sender.isConnected() ) {
            DataOutputStream outputStream =
                    new DataOutputStream( conn.getOutputStream() );
            
            outputStream.writeUTF("I love Oracle Java Magazine!");
        }
    }
    catch ( Exception e ) {
        e.printStackTrace();
    }

At this point, it’s important to know the expected application-level protocol. In the example above, Java String data is sent over the network. However, other Java Object data can be serialized and sent over the network using ObjectOutputStream and ObjectInputStream classes, as follows:

try {
        Socket sender = new Socket("localhost", 8080);
        if ( sender.isConnected() ) {
            ObjectOutputStream oos = 
              new ObjectOutputStream( 
                new BufferedOutputStream( sender.getOutputStream() ));
                    
            MyObject myObj = new MyObject();
            myObj.message = "I love Java!";
            myObj.messageId = getMessageId();
            // ...
            oos.writeObject( myObj );
            oos.flush();
        }
    }
    catch ( Exception e ) {
        e.printStackTrace();
    }

The listener on the other side connects as shown earlier, but it makes the blocking call wait for a serialized Java object to be returned.

ObjectInputStream ois =
    new ObjectInputStream( 
        new BufferedInputStream( client.getInputStream() ));
                
    MyObject myObject = (MyObject)ois.readObject();

Again, the protocol here is that both client and server agree to send serialized instances of MyObject objects over the network. The use of buffered I/O—using the BufferedOutputStream object—generally improves performance because the JVM efficiently handles the assembly of bytes into an Object internally.

Let’s talk about performance. My experience shows that as an application spends more time sending data over the network, CPU utilization will decrease, which means tuning your network application on a faster server won’t do much good. Instead, you need to improve your network I/O. A server with faster I/O capabilities might help, but that too will become saturated. You need to improve the design, and that means improving the code.

One improvement is to compress the data before it’s sent using a lossless algorithm (so you get back the original bytes). If you have an I/O-bound server, you can afford to spend some CPU processing time compressing the data, which will result in reduced network I/O.

By the way, this is one reason why web servers typically transmit images in compressed formats such as JPEG, because the picture consumes less I/O and bandwidth. When JPEG is used, however, the compression is lossy, so the uncompressed image is not precisely the same as the original. Lossy compression is fine for casual website viewing but is not acceptable for data processing.

Compressing the bytes

The JDK java.util.zip package provides classes for compressing and decompressing data, creating .zip and .gzip files, and much more. For this project, the appropriate classes are Deflater and Inflater, which compress and decompress bytes respectively. I’ll start by choosing the following compression algorithm:

Deflater compressor = new Deflater(Deflater.BEST_SPEED);

This compression algorithm prioritizes speed of execution—which uses minimal CPU resources but also results in less compression, that is, a larger output file. If you want as much compression as possible, which may require more processing time to compress the bytes, use Deflater.BEST_COMPRESSION. These compression options are part of a range you can use to balance the compression-to-speed ratio depending on your application, data type, data size, or other factors; you can see them all here in the “Field Summary” section.

Here is a sample sender that uses data compression.

DataOutputStream dos = 
    new DataOutputStream( conn.getOutputStream() );
byte[] bytes = messageTxt.getBytes("UTF-8");

// Compress the bytes
Deflater compressor = new Deflater(Deflater.BEST_SPEED);
compressor.setInput(bytes);
compressor.finish();
byte[] compressed = new byte[bytes.length];
length = compressor.deflate(compressed);

// Send the compressed data 
dos.write(compressed, 0, length);
dos.flush();

The code begins in a straightforward fashion, with a DataOutputStream and some message text. Assume the message is long, so there are many bytes to transmit.

Then it creates a Deflater set for best processing speed. The example above calls set Input to add bytes, and then it calls the finish() method. The class can also work with data streams. The subsequent call to deflate() compresses the bytes into the provided array, and the new (smaller) length is returned. Finally, the compressed bytes are sent over the network.

In one test application, I created messages of around 100 KB, and they each compressed down to just over 500 bytes. This is a significant savings in terms of network I/O time and bandwidth!

The following code reads and decompresses the bytes on the receiving end:

// Read the bytes
DataInputStream dis = new DataInputStream( instream );
byte[] compressed = new byte[ dis.available() ];
dis.readFully(compressed);

// Decompress the bytes
Inflater decompressor = new Inflater();
decompressor.setInput(compressed);
byte[] msgBytes = new byte[DEFAULT_SIZE];
decompressor.inflate(msgBytes);

String msg = new String(msgBytes);
System.out.println(msg);

First, a byte array is created to store the incoming bytes. Next, the Inflater class is used. The setInput() method is called to provide the compressed bytes, and then inflate() is called to decompress the bytes into the provided array. The resulting bytes are used to re-create the original string.

Adding flexibility and predictability

The process above works fine, but I have ideas for two improvements. The first is to add flexibility to compress the data only when that makes sense and not when it’s unnecessary. The second is to transmit the size of the byte array required for decompressing the string.

In my opinion, using getRemaining() and other Inflater methods to read the data in chunks is inefficient and complicated. I find it’s best to send both the uncompressed and compressed data sizes as int values in the data stream itself. In other words, the bits that arrive look like what’s shown in Table 1.

Table 1. Starting and ending bit sizes

Oracle Java, Java Exam, Java Exam Prep, Java Tutorial and Material, Java Guides, Java Certification, Java Prep, Java Preparation, Java Learning

Determining the sizes allows you to provide runtime flexibility in terms of compressing data only under the right conditions. For example, you can base your compression decisions on message size; if it’s only a few bytes, you don’t need to bother.

The enhanced sender code looks like the following:

DataOutputStream dos = 
    new DataOutputStream( conn.getOutputStream() );
byte[] bytes = messageTxt.getBytes("UTF-8");

// Write the original message length
int length = bytes.length;
dos.writeInt(length);

if ( length > LENGTH_THRESHOLD ) {
    // Compress the bytes
    Deflater compressor = new Deflater(Deflater.BEST_SPEED);
    compressor.setInput(bytes);
    compressor.finish();
    byte[] compressed = new byte[bytes.length];
    length = compressor.deflate(compressed);
}
else {
    compressed = bytes;
}

// Write the length again. If it was compressed, the
// sizes will vary, and this is the indicator that
// the data needs to be decompressed by the receiver
dos.writeInt(length);

// Write the data bytes
dos.write(compressed, 0, length);
dos.flush();

Of course, the receiver needs to change as well. The updated code is shown below.

DataInputStream dis = new DataInputStream( instream );

// Get the length of the next message
int msgSize = dis.readInt();

// Get the compressed size (if it's compressed
// this size will vary from the size above)
int compressedSize = dis.readInt();

// Read the bytes
byte[] compressed = new byte[compressedSize];
dis.readFully(compressed);

byte[] msgBytes = compressed;
if (compressedSize != msgSize) {
    // Decompress the bytes
    Inflater decompressor = new Inflater();
    decompressor.setInput(compressed);
    msgBytes = new byte[DEFAULT_SIZE];
    decompressor.inflate(msgBytes);
}

String msg = new String(msgBytes);
System.out.println(msg);

As you can see, the changes are minimal, but the result is very flexible and efficient code to decidedly and deterministically compress data to reduce I/O and network overhead when optimization criteria are met.

Source: oracle.com

Wednesday, October 19, 2022

Curly Braces #3: Let’s have fun with Java arrays

Elegant array development might encompass reflection, generics, and lambdas.

I was recently chatting with a colleague who develops in C. The conversation came to arrays and how very different they work in Java compared to C—which he found surprising given that Java is considered a C-like language.

Oracle Java arrays, Oracle Java Certification, Java Prep, Java Preparation, Java Tutorial and Materials, Java Guides, Java Cert Exam

This exploration of Java arrays starts simple but quickly gets interesting, especially if you studied or use C.

Declaring an array

If you follow a tutorial on Java, you’ll see there are two ways to declare an array. The first is straightforward.

int[] array; // a Java array declaration

You can see how it differs from C, where the following is the proper syntax:

int array[]; // a C array declaration

Focusing now on Java, after declaring an array you need to allocate it.

array = new int[10]; // Java array allocation

Can you declare and initialize an array in one step? Well, you cannot take a shortcut and do the following:

int[10] array; // NOPE, ERROR!

However, you can declare and initialize an array in one step if you already know the values.

int[] array = { 0, 1, 1, 2, 3, 5, 8 };

What if you don’t know the values? Here’s the code you’ll encounter more often to declare, allocate, and use an int array.

int[] array;

array = new int[10];

array[0] = 0;

array[1] = 1;

array[2] = 1;

array[3] = 2;

array[4] = 3;

array[5] = 5;

array[6] = 8;

...

Notice I specified an int array, which is an array of Java primitive data types. Let’s see what happens if you try the same process with an array of Java objects instead of primitives.

class SomeClass {

    int val;

    // …

}

SomeClass[] array = new SomeClass[10];

array[0].val = 0;

array[1].val = 1;

array[2].val = 1;

array[3].val = 2;

array[4].val = 3;

array[5].val = 5;

array[6].val = 8;

If you run the code above, you’ll get an exception as soon as you try to use the first array element. Why? Although the array is allocated, the array buckets each contain null object references. If you type this code into your IDE, it will even autocomplete the .val for you, so the error can be confusing. To resolve the error, do the following:

SomeClass[] array = new SomeClass[10];

for ( int i = 0; i < array.length; i++ ) {  //new code

    array[i] = new SomeClass();             //new code

}                                           //new code

array[0].val = 0;

array[1].val = 1;

array[2].val = 1;

array[3].val = 2;

array[4].val = 3;

array[5].val = 5;

array[6].val = 8;

That is not elegant. Indeed, it has often frustrated me that I cannot more easily allocate the array, and the objects within the array, by writing less code, maybe even all in one line.

Thus, I did some experimenting.

Finding Java array nirvana

The goal here is coding elegance, not to be a purist. Smells like “clean code” spirit! And in that spirit, I set out to create some reusable code to clean up the array allocation pattern. Here’s a first attempt.

public class MyArray {

    public static Object[] toArray(Class cls, int size) 

      throws Exception {

        Constructor ctor = cls.getConstructors()[0];

        Object[] objects = new Object[size];

        for ( int i = 0; i < size; i++ ) {

            objects[i] = ctor.newInstance();

        }

        return objects;

    }

    public static void main(String[] args) throws Exception {

        SomeClass[] array1 = (SomeClass[])MyArray.toArray(SomeClass.class, 32); // see this

        System.out.println(array1);

    }

}

The one line of code marked as “see this” is elegant and looks just the way I wanted, thanks to the implementation of toArray. This approach uses reflection to find the default constructor for the provided class, and then it calls that constructor to instantiate an object of this class. The process calls the constructor once for each element of the array. Brilliant!

Too bad it doesn’t work.

The code compiles fine but results in a ClassCastException when you run it. To use this code, you need to create an array of Object elements and then cast each array element to class SomeClass, as follows:

Object[] objects = MyArray.toArray(SomeClass.class, 32);

SomeClass scObj = (SomeClass)objects[0];

...

That isn’t elegant! After more experimentation, I evolved several solutions that use reflection, generics, and lambdas.

Solution 1: Use reflection

The answer to the issues above is to use the java.lang.reflect.Array class to instantiate an array of the class you specify, instead of using the base java.lang.Object class. This is essentially a single-line code change that gets closer to the goal.

public static Object[] toArray(Class cls, int size) throws Exception {

    Constructor ctor = cls.getConstructors()[0];

    Object array = Array.newInstance(cls, size);  // new code

    for ( int i = 0; i < size; i++ ) {

        Array.set(array, i, ctor.newInstance());  // new code

    }

    return (Object[])array;

}

You can use this approach to get an array of the class you desire, and then operate on it as follows:

SomeClass[] array1 = (SomeClass[])MyArray.toArray(SomeClass.class, 32);

Although it’s not a necessary change, the second line was modified to use reflection’s Array class to set each array element’s content. This is great! But there’s one more detail that does not feel quite right: That cast to SomeClass[] isn’t elegant. Fortunately, there is a solution with generics.

Solution 2: Use generics

The Collections framework uses generics to be type-specific and eliminate casts in many of their operations. You can use generics here as well. Take java.util.List, for example.

List list = new ArrayList();

list.add( new SomeClass() );

SomeClass sc = list.get(0); // Error, needs a cast unless...

The third line in the above snippet will result in an error, unless you update the first line as follows:

List<SomeClass> = new ArrayList();

You can achieve the same result using generics in the MyArray class. Here’s the new version.

public class MyArray<E> {

    public <E> E[] toArray(Class cls, int size) throws Exception {

        E[] array = (E[])Array.newInstance(cls, size);

        Constructor ctor = cls.getConstructors()[0];

        for ( int element = 0; element < array.length; element++ ) {

            Array.set(array, element, ctor.newInstance());

        }

        return arrayOfGenericType;

    }

}

// ...

MyArray<SomeClass> a1 = new MyArray(SomeClass.class, 32);

SomeClass[] array1 = a1.toArray();

This looks good. By using generics and including the target type in the declaration, the type can be inferred in other operations. In fact, this code can be reduced to a single line, as follows, if you choose:

SomeClass[] array = new MyArray<SomeClass>(SomeClass.class, 32).toArray();

Mission accomplished, right? Well, not quite. This is fine if you don’t care which class constructor you’re calling, but if you want to call a specific constructor, this solution falls short. You can continue to use reflection to solve this problem, but the code may get complex. Fortunately, lambdas offer another solution.

Solution 3: Use lambdas

I’ll admit, I was slow to adopt lambdas, but I’ve grown to appreciate their value. In particular, I’ve come to appreciate the java.util.stream.Stream interface, which processes collections of objects. Stream helped me achieve Java array nirvana.

Here’s my first attempt to use lambdas.

SomeClass[] array = 

    Stream.generate(() -> new SomeClass())

    .toArray(SomeClass[]::new);

I broke this code across three lines for readability. You can see it checks all the boxes: It is simple and elegant, creates a populated array of instantiated objects, and allows you to call a specific constructor.

Notice the parameter to the toArray method: SomeClass[]::new. This is a generator function used to allocate an array of the specified type.

However, as it stands, this code has a minor issue: It creates an array of infinite size. That is suboptimal. Fortunately, this can be resolved by calling the limit method.

SomeClass[] array = 

    Stream.generate(() -> new SomeClass())

    .limit(32)   // calling the limit method

    .toArray(SomeClass[]::new);

The array is now limited to 32 elements. You can even set specific object values for each array element, as in the following:

SomeClass[] array = Stream.generate(() -> {

    SomeClass result = new SomeClass();

    result.val = 16;

    return result;

    })

    .limit(32)

    .toArray(SomeClass[]::new);

This code demonstrates the power of lambdas, but the code is not neat and compact. Calling a different constructor to set the value is much cleaner, in my opinion.

SomeClass[] array6 = Stream.generate( () -> new SomeClass(16) )

    .limit(32)

    .toArray(SomeClass[]::new);

I like the lambda-based solution, which is ideal when you need to call a specific constructor or operate on each array element. When I need something more basic, I tend to use the solution based on generics since it’s simpler. However, you can see that lambdas provide an elegant and flexible solution.

Source: oracle.com

Monday, October 17, 2022

Unique Java Card verification and deployment model

Oracle Java, Java Career, Java Skill, Java Jobs, Java Tutorial and Material, Java Certification, Java Preparation, Java Guides, Java Learning

A key concept in security is "defence in depth”: multiple controls must be performed in sequence to guaranty Confidentiality, Integrity and Availability of sensitive assets.

Java Card products and associated security services are examples of such assets. They are a critical enabler in our day-to-day lives: to pay at a shop, make a phone call, cross a border with a passport or to provide trusted and genuine data to IoT clouds for AI processing. The deployment of Java Card applications relies on an established ecosystem of hundreds of companies and organizations, organized around security practices that guarantee this defence in depth. The three pillars of this deployment model are code verification, chain of trust and certification.​
 

Java Security and verification


As with any Java-based Virtual Machine, a fundamental feature of the Java Card Virtual Machine is the security provided by bytecode verification. A verifier checks the structure of a Java Card Converted Applet (CAP) file - the file format for Java Card applications - and perform bytecode verification ensuring type safety. Code verification is always a mandatory step. It must be performed in the deployment process of an application to prevent against security risks induced by malformed code. We will see however, that Java Card offers some flexibility to determine when and how verification must be applied.

The Java Card Virtual Machine, Runtime Environment and APIs are designed to run security services on tamper-resistant, secure hardware, and in many cases with limited memory and CPU resources. Some secure elements for example may only have 2 or 4 KB of RAM, and 16-32 bit CPUs. On very resource-constrained hardware, a Java Card implementation may not have enough memory to perform verification on the device itself. To address this scenario, the Java Card specification includes a stand-out feature in allowing a split-VM architecture: verification can either be processed inside the device (on-device or on-card verification) as is the case for the standard Java Virtual Machine for example, or outside the device with an off-device or off-card verifier tool coming with an abstract interpreter.

To support that flexibility, Oracle provides the Java Card Off-Card verifier as a standard tool that can be used for off-device verification. Other similar tools may be available from Java Card licensees.

When verification is performed off-device, several security conditions need to be enforced to prevent execution of corrupted code:

◉ The latest version of the verifier tool needs to be used to perform up-to-date security checks. In the case of the Oracle Java Card Verifier, the latest version can be found as a free download on the Oracle website.
◉ Verification must use export files that are binary compatible with API packages installed on the device.
◉ After verification, the CAP file to be executed on the device is not altered in a way that does not satisfy the constraints checked by this verification.

Another aspect of the split-VM architecture is that data needed for verification is optional and packaged separately from the data needed for the actual execution of the code within a CAP file. This design avoids embedding data that would be unused by a product without on-device verification capabilities. The deployment model acknowledges that a Java Card application can be installed by multiple service providers, managing the installation of optional CAP file components (including those used for verification) in a variety of ways, and on Java Card products with different on-device verification capabilities.

As a consequence, even if off-device verification is not strictly a mandate in the specs (it can be done on-device instead), off-device verification has become a pre-requisite in the Java Card deployment ecosystem. Systematic off-card verification ensures that verification is performed, independently of the on-device capabilities of Java Card product that may be rolled out in future phases of deployment.

Chain of Trust and AAA+ service


The second pillar of the deployment model is based on application management  and communication protocols, such as the ones defined by GlobalPlatform, to securely administrate a Java Card product: installation, update, removal of applications and credentials associated with applications. The principle is to enforce a chain of trust starting from the source of a CAP file and based on a AAA+ service: identification, authentication, authorization, Accountability/non-repudiation are guaranteed for each management operation.

CAP files are installed on a Java Card product either at manufacture with specific accreditation and certification, or once deployed in the field by using a Remote Service Manager and through secure channels. In any case, cryptographic keys guarantee an application deployment is secure (confidentiality and integrity) and performed only by an authenticated entity having a granted authorization. In other words, keys are needed to administrate a Java Card product, and it is not possible to install an application without breaking the chain of trust that manages those keys.

The entity or entities deploying applications must anticipate the range of on-device verification capabilities of the targeted Java Card products, and will deploy applications only having the guarantee that the code is verified at some point in time prior its execution either off-device or on-device. As mentioned in the previous section, state of the art is to perform verification of applications off-device prior any deployment to avoid any risk: even if verification is also performed on-device, it prevents from having a corrupted CAP file that may lead to a denial of service for instance.
 

Security Evaluation & Certification


Products certification is the only mean to bring trust in an open ecosystem. Java Card is widely used in Finance, ID, Mobile and IoT markets. Without trust no one can accept to be liable for a given business risk.

To facilitate Common Criteria certification, Oracle provides a Java Card Protection Profile that helps vendors meet the demand of banks, governments, and other secure device issuers for security evaluations. Verification is a mandatory requirement in order to obtain Common Criteria certification, and is required by the Java Card protection profile.

In addition, in order to adhere to hardware and software certification requirements or as an additional product differentiation, Java Card vendors may choose to have additional and different types of security checks that are performed at runtime, focusing on the execution behavior such as:

◉ security counter measures against logical attacks that may happen if the integrity of the flow from verification to the installation is compromised or memory corrupted after code has been installed in the device: protection against stack or objects overflows, invalid execution paths or illegal code jump, illegal entry point access, type confusion ...

◉ or counter measures against physical attacks, faults attacks or side channel attacks that may happen during execution. 

Depending on the deployment scenario (e.g. multiple entities authorized to provide applications for a device), or the condition of utilization of a device (e.g. devices exposed to high risk of physical attacks or lacking hardware countermeasures), application deployers may elect to choose Java Card products with those additional security checks, as an additional protection layer in addition to verification and a chain of trust.

Source: oracle.com

Friday, October 14, 2022

Implement Interface using Abstract Class in Java

Java Interface, Abstract Class, Java Career, Java Prep, Java Preparation, Java Tutorial and Materials, Java Certification, Java Jobs

Interface contains only abstract methods that can’t be instantiated and it is declared by keyword interface. A class that is declared with the abstract keyword is known as an abstract class in Java. This is a class that usually contains at least one abstract method which can’t be instantiated and It is also possible for the class to have no methods at all. The instance of an abstract class can’t be created.

Now as all methods in an interface are abstract methods therefore we can implement it using Abstract Class.

1. Let’s create an Interface at first:


// creating an interface named ORACLEJAVACERTIFIED 
interface ORACLEJAVACERTIFIED { 
void learnCoding(); 
void learnProgrammingLanguage(); 
void contribute(); 
}

Here the three  non-implemented methods are the abstract methods

2. Now let’s implement the interface in an Abstract class named Student:


// creating an abstract class named Student which is 
// implementing the interface,ORACLEJAVACERTIFIED 
abstract class Student implements ORACLEJAVACERTIFIED { 
// Overriding two methods of the interfacem,ORACLEJAVACERTIFIED
@Override public void learnCoding() 
System.out.println( 
"Let's make coding a habit with ORACLEJAVACERTIFIED"); 
@Override public void learnProgrammingLanguage() 
System.out.println( 
"Let's master all fundamentals of java with the help of ORACLEJAVACERTIFIED"); 
}

Here we have overridden two abstract methods of the interface ORACLEJAVACERTIFIED.

3. Now let’s create a class JAVA which extends the abstract class, Student:


As previously mentioned, we can’t create an instance of our abstract class therefore we need to make a non-abstract class.

// creating an non-abstract class 
// JAVA which is extending Student 
class JAVA extends Student { 
// overriding the remaining method of the interface,ORACLEJAVACERTIFIED 
@Override public void contribute() 
System.out.println( 
"Now let's help others by contributing in ORACLEJAVACERTIFIED"); 
}

Here we have overridden the remaining method of the interface ORACLEJAVACERTIFIED.

Below is the overall implementation of the problem statement:

// Implemention of Interface using Abstract Class in Java 

// Interface ORACLEJAVACERTIFIED 
interface ORACLEJAVACERTIFIED { 
void learnCoding(); 
void learnProgrammingLanguage(); 
void contribute(); 

// Abstract class Student implementing from ORACLEJAVACERTIFIED interface 
abstract class Student implements ORACLEJAVACERTIFIED { 

// Overriding the methods 
@Override public void learnCoding() 
System.out.println( 
"Let's make coding a habit with ORACLEJAVACERTIFIED"); 
@Override public void learnProgrammingLanguage() 
System.out.println( 
"Let's master all fundamentals of java with the help of ORACLEJAVACERTIFIED"); 

// Extend the JAVA class by Student abstract class 
class JAVA extends Student { 
@Override public void contribute() 
System.out.println( 
"Now let's help others by contributing in ORACLEJAVACERTIFIED"); 

// Driver code 
public class Main { 
public static void main(String[] args) 
// New JAVA object is created 
JAVA oraclejavacertifiedStudent = new JAVA(); 

// Calls to the multiple functions 
oraclejavacertifiedStudent.learnCoding(); 
oraclejavacertifiedStudent.learnProgrammingLanguage(); 
oraclejavacertifiedStudent.contribute(); 
}

Output:


Let's make coding a habit with ORACLEJAVACERTIFIED
Let's master all fundamentals of java with the help of ORACLEJAVACERTIFIED
Now let's help others by contributing in ORACLEJAVACERTIFIED

Source: geeksforgeeks.org

Wednesday, October 12, 2022

GraalVM Enterprise 22.2—Lower memory, smaller downloads, simpler library usage

GraalVM Enterprise 22.2, Oracle Java Prep, Oracle Java Certification, Oracle Java Career, Oracle Java Tutorial and Materials, Oracle Java Certification

The GraalVM Enterprise 22.2 release includes much anticipated Apple M1 support, a significant reduction in the memory requirements of Native Image, a smaller base JDK distribution package, and an exciting new facility to make it easier to use third-party libraries in your Native Image compiled applications.

Apple Silicon M1/M2


If you don't already have an Apple silicon M1/M2 laptop you're probably thinking about joining the many developers who have raved about its excellent performance, low power consumption, and typically silent operation.  Developers who do have one can now try out GraalVM Enterprise 22.2's new experimental support for Apple silicon and see what the combination of cutting-edge hardware and advanced compiler technology can do!  Running GraalVM Enterprise Native Image on Apple silicon is significantly faster than on Intel Macs improving day-to-day developer productivity.

Slimmed Down JDK


In addition to core Java support, GraalVM Enterprise provides many optionally installable packages supporting several programming languages including Python, Ruby, and R.  To make it easier for developers to get just the components they need we've streamlined the base GraalVM Enterprise installation bundle so that it is smaller and more modular.  You can now download just the GraalVM Enterprise JDK to run Java applications on the JVM.  The reduction in size is immediately visible in the download packages.  For example, in the previous 22.1 release the core Linux amd64 download was 518 MB.  In 22.2 the new JDK download for the same OS and architecture is only 217 MB, a reduction of almost 60%!  Being able to download just the JDK is especially useful if you're deploying your Java app in a container where it's important to keep image size low.  If you do want to use Native Image, VisualVM, or any of the GraalVM supported languages, it's easy to install those components on top of the base JDK.  The choice is yours.

Lower Memory Requirements


With every release, GraalVM Native Image get faster, smarter, and leaner.  In the recent past, 21.3 achieved performance on par with the JVM, 22.0 introduced much more user friendly output, 22.1 delivered faster compilations and a new quick build mode to improve the developer experience.  Now in 22.2 Native Image has cut its memory needs in half!  GraalVM Native Image is written in Java and typically more memory for a Java app leads to better performance.  Most developer machines have plenty, but CI/CD build machines (runners) tend to be more constrained.  For example, free GitHub Actions are limited to 7GB and Oracle Cloud Infrastructure DevOps runners are (currently) limited to 8GB.  With the 22.2 release, GraalVM Native Image can be used on both of those CI/CD platforms to successfully build applications without encountering an out-of-memory error.  Of course, you could always pay for bigger build runners, but thanks to lower memory requirements, GraalVM Enterprise 22.2 can help keep your costs down!

Third-Party Libraries and Native Image


GraalVM Native Image takes a closed-world approach to determine what classes, methods, and fields are compiled into a native executable.  Starting from your application entry point, Native Image performs static analysis to determine all the reachable code that needs to be included.  Unreachable code is excluded from the generated native executable.  This is great in general and the approach works very well with modern frameworks such as Micronaut.  However, many libraries and frameworks use dynamic Java features (such as reflection) that obscure code paths from static analysis.  For such libraries it's necessary to provide Native Image with additional reachability metadata to ensure all required code is included in the final executable.

In GraalVM 22.2, to make it easier to use popular libraries that require additional reachability metadata, the Oracle GraalVM team in conjunction with the Spring and Quarkus teams have created a GitHub repository where metadata for popular libraries can be published.  Using this metadata is as easy as setting a property in the GraalVM Native Build Tools Maven or Gradle plugins.  For example, in Gradle you can enable use of the reachability metadata repository with:

graalvmNative {
    metadataRepository {
        enabled = true
    }
}

For more details, see the Maven and Gradle plugin guides and try out an example.

Wrapping Up


Release to release, GraalVM Enterprise delivers additional performance optimizations and improvements in Native Image compilation time, generated executable size, and developer productivity.  For a complete list of all the changes in GraalVM 22.2 browse the release notes.

GraalVM Enterprise is included in the Oracle Java SE Subscription and is available at no additional cost for use on Oracle Cloud Infrastructure. Download the latest release today!

Source: oracle.com

Tuesday, October 11, 2022

Quiz yourself: Java’s sealed classes and instanceof checks

Java’s Sealed Classes, Core Java, Oracle Java Prep, Oracle Java Certification, Oracle Java Learning, Oracle Java Prep, Oracle Java Tutorial and Materials

What does the Java compiler do when it encounters an instanceof expression?


Given the full code of an interface and three classes

public interface Loggable {
    static boolean isLoggable(Process p) {
        return p instanceof Loggable;
    }
}

sealed class Process permits SlowProcess, FastProcess {
}

final class SlowProcess extends Process {
}

non-sealed class FastProcess extends Process {
}

Which statement is true? Choose one.

A. The code compiles successfully as it is.

B. In order to make the code compilable, the final modifier from SlowProcess class must be removed.

C. In order to make the code compilable, the Process class must implement the Loggable interface.

D. In order to make the code compilable, the non-sealed modifier from FastProcess class must be replaced with the final modifier.

Answer. This question explores limitations added by sealed classes on instanceof checks.

The instanceof expression tests a value against a type. When the compiler comes across an instanceof expression, the compiler first determines if the expression can be shown to be definitely false by static analysis. In such a case, the expression causes a compilation error. A readily understood example of this kind of impossible instanceof is illustrated by the following code:

void compilerError(String s) {
  // compiler rejects this instanceof test
  boolean impossible = s instanceof StringBuilder;

The analysis is a little more subtle where interfaces are concerned, and more examples can help clarify the issue. First, the following example compiles successfully:

interface SomeInterface {
  void doStuff();
}
// and later the test:
void test(BufferedWriter x) {
  boolean test = x instanceof SomeInterface;

The reason this compiles is that even though SomeInterface is clearly a new interface and BufferedWriter does not implement it, the BufferedWriter class is not final. That means it’s possible that elsewhere, or in the future, a subclass of BufferedWriter might exist that implements SomeInterface. Because the compiler doesn’t know, it doesn’t signal a compilation error.

The next example shows another use of instanceof that fails to compile.

void compilerError(String x) {
  boolean test = x instanceof Runnable;

In this case, Runnable is an interface and String does not implement Runnable. At this point, the code seems very similar to the previous example. However, this example fails because String is a final class, and because it’s final, there is no chance of a subclass existing elsewhere. Therefore, there is no chance that a subclass exists that implements Runnable.

This type of logic is also applied to the situation in this exam question.

The instanceof expression in the question tests a reference of type Process to see if the object referred to by that reference implements the Loggable interface. Now, in the typical situation, all types that can ever be assignment-compatible with a sealed class will be known to the compiler, and if none implements the interface in question, the compiler could reject the code outright.

However, in this case, the FastProcess class is marked non-sealed, and because of this, it’s possible for this class to have subclasses that are not known to the compiler at this time, and those subclasses might possibly implement the Loggable interface. Because of this possibility, the compiler accepts the code and compiles the test as written. Therefore, the code will compile successfully as it is, and option A is correct.

The subclasses of a sealed class must explicitly list one of these modifiers: sealed, non-sealed, or final. Removing the final keyword would cause an error, and from this you can determine that option B is incorrect.

Option C proposes a solution to fix a compilation error, but as you have already seen, there’s nothing wrong with the code. Implementing the Loggable interface by the Process class would be entirely valid but is not required to fix the code. Because of this, you can determine that option C is incorrect.

Option D suggests replacing non-sealed with the final modifier. However, this would guarantee that no subtype of Process could exist that would pass the instanceof test—and therefore the change will actually result in compilation failure. This tells you that option D is incorrect.

Conclusion. The correct answer is option A.

Source: oracle.com

Monday, October 10, 2022

Go deep at JavaOne: 20 developer sessions that caught my eye

Oracle Java, Oracle Java Prep, Oracle Java Preparation, Oracle Java Tutorial and Material, Oracle Java Guides, Java Skills, Java Jobs, Java Certified

What are the latest and greatest features of Java? Where is the platform going? How can you leverage Java’s capabilities to build better application—while also enhancing your own skills as a developer?

You’ll find these topics addressed in the technical learning sessions, labs, workshops, and solutions keynotes at the JavaOne Conference, October 17-20, 2022, in Las Vegas.

The conference offers 135 sessions covering all aspects of the language and run-time platform, as well as interoperability and integration with other technologies such as Linux, GitHub, and Spring Boot.
Many of the session leaders are engineers working in the Oracle Java Platform Group, and many also come from the broader community. For example, you can learn from a rock star in the Java world, Venkat Subramaniam, president of Agile Developer Inc., by catching his class “Functional Programming Idioms in Java.”

By the way, JavaOne is collocated with the Oracle CloudWorld Conference, and as an attendee of JavaOne, you can welcome to attend any of the CloudWorld sessions, keynotes, and other events.

Here are some of the JavaOne sessions that I personally find most interesting, but feel free to peruse the entire catalog—or just jump in and register now:

Java First. Java Always.


Modern application development is unrecognizable without Java. For more than 25 years, Java has empowered developers to create the next generation of rich, scalable, and secure applications. In this keynote, learn how Oracle’s ongoing Java leadership and stewardship is creating a contemporary language and platform that helps developer productivity.

Data-Oriented Programming with Records, Sealed Classes, Text Blocks, and More


Java has undergone rapid evolution in the past several years. Many of the new features, while surely useful on their own, are designed to work together. See how three of the recent features—records, sealed classes, and pattern matching—work together to enable a data-oriented style of programming, which is a good match for today's cloud applications.

Developing Long-Lasting Java Microservices


Modern Java development is about simplicity and productivity; the days of ceremony are long gone. We explore what can make an application "modern" and, more importantly, which code practices can help sustain that "modern" feeling—and keep the "legacy" out. See code examples and their consequences (based on code from a global financial super-app), and modern Java Development Kit, naturally.

Evolving the Security of the Java Platform


Maintaining and improving the security of the Java Platform is an essential and continuous process. We discuss recent improvements to the security and cryptographic APIs and libraries, as well as the process and changes made to update releases via the Java Cryptographic Roadmap.

CI/CD, Github Actions, and GraalVM Native Image


For cloud applications, generating a native executable using GraalVM Native Image is often the final build step. Fortunately, new GraalVM Native Image support for GitHub actions makes it easy to incorporate ahead-of-time compilation into a GitHub build pipeline. We look at incorporating GraalVM Native Image compilation into continuous integration and continuous delivery pipelines—including GitHub with GitHub actions—along with generating executables for multiple platforms such as Windows, macOS, and Linux.

Accelerate Java Cloud Native DevOps with Oracle Linux and Oracle VM VirtualBox 


How do you simplify Java cloud native development and deployment? Oracle Linux offers an open, integrated operating environment with application development tools, management tools, containers, and orchestration capabilities. Plus, there are open-source Cloud Native Computing Foundation projects such as Kubernetes, RunC, CRI-O, Kata Containers, and Istio. Learn how to accelerate your DevOps using these resources, and efficiently build reliable, secure cloud native Java applications. See how to create, maintain, and deploy your Java apps across hybrid cloud environments, with an open-source stack that is tested, integrated, and supported worldwide by Oracle.

Functional Programming Idioms in Java


Many developers and organizations are immersed in Java's functional programming capabilities. Writing code is easy, but writing maintainable code takes effort, discipline, and care. What are some of the dos and don'ts we should keep in mind when programming in functional style? Spot the common mistakes you may have seen in your code base and learn several supporting pieces of evidence for why we should avoid these mistakes and how to write better quality functional style code.

How to Avoid Common Pitfalls with Modern Microservices Testing


Have you ever wondered why your microservices break in production after all the tests passed during continuous integration/continuous delivery (CI/CD)? Have you wondered if you're testing too much or too little? Learn about common pitfalls and how to catch them at build time rather than runtime. We share some common battle scars observed in the wild and introduce the testing pyramid—explaining how it allows you to continuously deploy microservices independently without fear. We demonstrate, through a test-driven development approach, how combining Pact contract testing with Quarkus developer joy can help prevent your microservices from breaking in production.

How to Run Your Application up to 60X Faster with Native Images


In a world with more and more distributed applications with no state control, performance is one of the biggest challenges (being related to startup or even to the response to the first request). For a while, this context made Java a dubious choice for approaches like serverless, microservices, and containers. Today we not only have platforms that take Java to a brand-new performance level; we also have something that allows us to take a step further: the native images built using GraalVM. Learn what can and can't be done with native images, and how you can run your code up to 60X faster today.

Jakarta EE 10: Simplicity for Modern and Lightweight Cloud Applications


Jakarta EE 10 is packed with new features that make it easy to develop modern, lightweight enterprise Java applications for the cloud. The new Jakarta EE Core Profile helps develop microservices with Jakarta EE technologies with runtimes smaller than ever. It even makes compiling Jakarta EE applications to native images possible—to reduce the footprint even further. We explore Jakarta EE 10's new features in an interactive way packed with live code demos. We also talk about what we can expect from the future of Jakarta EE.

Java and the Promise of Quantum Computing


We've all heard the hype: Quantum computers will leave our current machines wallowing in the dust. Quantum algorithms will crack our existing encryption schemes in seconds. Will it really happen? The answer depends on engineering problems that have yet to be solved. But for those who write code, many insights are already available. This lab lets you run Java code using Johan Vos's Strange platform. We use the code to learn about quantum computing's revolutionary approach to problem solving.

Java + Project Loom = Synchronous Performance


We long were forced to choose: either use complicated and performant reactive code, or use a simple (yet limited) synchronous approach. Thanks to Project Loom, the paradigm can shift once more—even for applications that require high concurrency. We introduce a server designed for Loom with fully synchronous routing that can block as needed, yet still provide high performance under heavy concurrent load. We then dive a bit deeper to show the advantages of Project Loom, design choices made, and the implementation of other protocols, such as HTTP/1.1, HTTP/2, gRPC, and WebSocket.

(Mis)Understanding Cloud Native Java


Cloud is great, and cloud native is really nice. However, some misconceptions and terms are often thrown around—from JDK distributions and memory footprints to startup times, health probes, observability, serverless Java apps, zero downtime, and many more. Some can be confusing, and some even intimidating. We try to bust a few myths about cloud native development and give you some pointers on how you can develop better and more modern applications.

New Java features: Simplified Design Patterns


Java is often accused of being too verbose. We show how new and announced features and syntactic improvements in Java are helping to reduce the truth of this. We examine how newly added features and semantic improvements contribute to our code's simplification, maintainability, and efficiency. Find out how to use these new features to solve everyday challenges. We show a beauty of pattern matching, Records, Sealed classes and more on commonly used design patterns.

Refactoring Rules: How and When to Refactor Java Code


Test-driven development (TDD) is a multistep process, but most developers skip the last step (refactoring) because they aren't confident in how to do it. The test is green, right? Isn't that what's supposed to happen on TDD? Not really... Thinking like this leads to a fragile pile of code that ends up causing more harm than good. This fast-paced, action-focused presentation shares refactoring guidelines you can quickly apply to any piece of code—letting you turn your first draft into a flexible and maintainable design. With a little practice, the refactoring step will be another fun part of the development cycle.

Supercharge Your Java Code for Optimal Database Performance


Java is lightning-fast and powerful but, when a database is part of the stack, application performance can quickly hit a bottleneck. For years, databases have been seen as the slow, monolithic backends that limit throughput. But are they the real culprits? Not necessarily. Most of the time, the code—using autocommit, too many network round-trips, and unnecessary work on the database end—is the issue. We show some of these pitfalls and how to avoid them using code refactoring and simple tricks to supercharge your application. Learn the fundamentals of database performance and never wait for a reply from your DBA again.

Training and Tracking Machine Learning Models in Java with Tribuo


Tribuo is a Java machine learning (ML) library, developed by Oracle Labs, used inside Oracle since 2017, and open sourced in 2020. It has several features that make it suitable for enterprise deployments of ML models. It can train and deploy ML models in Java and tracks the provenance of the models it trains. Each model is self-describing; it knows its training data, how that data was processed, and all the algorithmic details that went into building it. Tribuo also can export models in ONNX format and integrates with popular libraries like TensorFlow and XGBoost. Get introduced to Tribuo, learn how to use it for a variety of ML tasks, and watch as we demonstrate its integrated provenance features.

Your Guide to OpenJDK Development


Java, its libraries, and Java HotSpot VM are all built through OpenJDK, an open-source project. The OpenJDK Developers’ Guide aligns developers around terminology and process. Learn how you can contribute to the project.

The Future of Java Is You


Not only does Oracle take our Java leadership seriously, we also embrace our stewardship of the Java community. As the Java language and platform evolves to rapidly address modern application development, Oracle continues to invest in the Java community to ensure it remains one of the strongest developer ecosystems on the planet. In this keynote, learn about the many Java community programs from Oracle that give developers a voice in shaping the future of Java.

Source: oracle.com