Features of Java
Language paradigms: Procedural programming.
- To understand how JAVA improves object-oriented features.
- To learn how to write inline functions for efficiency and performance.
- To learn the syntax and semantics of the JAVA programming language.
- To learn how to design JAVA classes for code reuse.
- Applications of JAVA
- Desktop GUI Applications: Java provides GUI development through various means like Abstract Windowing Toolkit (AWT), Swing and JavaFX. …
- Mobile Applications: …
- Embedded Systems: …
- Web Applications: …
- Web Servers and Application Servers: …
- Enterprise Applications: …
- Scientific Applications
- JAVA can also be used in the making of Android Applications now it is replaced by Kotlin.
Java follows a simple policy that writes once run everywhere. Java’s platform-independent character makes it possible. Java’s byte codes are portable to any platform. Once the byte code is ported. JVM then makes the equivalent machine-specific code.
The second feature of making portable is the size of primitive data types as they are fixed length irrespective of the underlying platform.
One difficulty inherent in any API that attempts to provide cross-platform functionality is the lowest common denominator problem. Even though there are several overlaps between operating systems but they have several distinct differences.
A java API that aims to give programs access to the system services of any operating system, needs to decide and pick the capabilities to support. Generally, Java API developers support most of the common features but they may not support all.
As a result, Java API lacks the features which may be required for you.
The syntax is similar to C, C++,so upgrading from these languages are easier. However, fresh learning is also possible with ease.
- No multiple inheritance hence less ambiguity.
- No global variable concept.
- No usage of the pointer and no usage of pointer arithmetic.
- No operator overloading.
- No concept of garbage value in Java. (Must initialize the variables)
Java is a highly secured language. It gets executed inside a JVM(Java Virtual Machine). Java has a set of the class loader to load class files. These class files may come from local machine or network. The classes are not allowed to directly read/write files on the local machine. The Byte code verifier checks and verifies the class if it is a valid Java class.
Java’s security model is divided into three basic components:-
- Byte code verifier
- Security manager
- Security – Java provides a default firewall between the internet and our Java
The Security Manager then controls various critical operations by checking the permissions.
Java’s security model focuses on protecting clients from malicious code that can be downloaded from the network from an untrusted source. To achieve this Java provides customizable “sandbox” when the malicious Java code can be placed. The “sandbox” however stops the activities of the malicious code.
Java security becomes vital when –
- Reading and writing to the local disk.
- Making a network connection (untrusted).
- Grating a new process.
- Loading in new dynamic link library.
The sandbox model, however, works on code signing and authentication. (signing mean digital signature)
The sandbox itself access any code from anywhere. But the security prevents the code from gaining access that we do not trust. The sandbox itself stops the code from taking any action.
The fundamental components for Java Sandbox are-
- The class loader architecture.
- The class file verifiers.
- Safety feature built into Java Virtual Machine and the Java language.
- The Security Manager.
- The Java APIs design.
As the class loader and security manager are customizable, we can put our own customized security policy.
The readymade security manager provides us with the security policy in an ASCII policy file different from the program. The access controller enforces security policies.
Java is almost a pure object-oriented language with primitive data type support.
Java is an efficient manager of the memory and controls the exception during runtime very well. Efficient memory allocation and deallocation eliminates many dynamic memory management related issues.
Besides performance issues, Java’s other issues are the lack of control of memory management and thread scheduling.
Garbage collection, surely makes a Java code more robust by providing valuable security guarantee in the networked environment. But garbage collection puts a level of uncertainty to the runtime performance of the program.
[The coders are not sure when or if a garbage collector will execute and how long the process will take to finish].
With the help of multithreading, Java can produce many interactive, networked applications which can perform several operations concurrently.
The looseness in the specification of thread actually helps to port the Java virtual machine to many different kinds of hardware. The coders have no control over the thread scheduling algorithm.
Java is fully neutral of the surrounding architecture ( like an OS upgrade/downgrade, Processor upgrade/downgrade, change in the core system etc.)
Supports Native Methods
Our program heavily depends on Java’s platform version along with the ability to call native methods. Calling the native methods that are not part of Java API is the key to render our code to become platforms-specific.
Calling of native methods are useful in the below-written scenarios –
- For accessing features of an underlying host platform that are not accessed able through the Java APIs.
- For accessing a legacy system.
- For reusing an already existing library written in any other language other than Java.
- For speeding up the performance of a program by implementing time-critical code as native code.
If we need to use our custom native methods on multiple hosts, we need to port them on these hosts in an old-style way. However, our primary goal will be to avoid these native methods as far as possible and use Java’s APIs to do our job.
Supports Non-standard runtime libraries
Native methods are generally compatible with the operating systems. This feature gives several vendors an opportunity to supply standard runtime libraries of Java APIs. Apart from standard runtime libraries, these vendors may also supply extra libraries.
They may be platform-independent or may not be. So, while designing we need to be careful while calling native methods. Now, non- standard libraries that do not call any native methods, will not impact (degrade or upgrade our coding performance and platform independence.
But using non-standard libraries to call native methods are equivalent to call them (native methods directly). Rather, it is extra overhead for our code. However, this usage of non-standard library renders our program platform-specific.
Interpreted and high performance:- ahead of time compilation
Java is a compiled an interpreted language, it is fast in execution.
Since Java’s security and mobility costs us the performance trade-off. Here are four strategies that can beat the trade-off –
We need to
- Deliver a virtual-machine along with our code.
- We need to implement time-critical sections of our program as native methods.
- We can compile the whole program to a monolithic executable like c or c++.
- We can compile to a monolithic executable at the end user’s machine at install time.
While delivering a separate custom-made virtual machine or able to pick the required virtual machine will surely boost the performance of our program. Being able to execute part of our Codebase natively is the best approach. But it is an overhead for our development team.
The sprint model is overkill to the development team. Along with the deliverables specified in a sprint this design of extra Code to get the virtual machine or to design a new one surely slows down the actual development effort.
Compiling the Java source code to a monolithic executable referred to as ‘ahead of time’ compilation. This can help to boost performance. But one downside of this approach is to destroy’s the java’s dynamic extension capabilities as ahead of time compilation is static, not dynamic in nature.
If your code is not following dynamic extensions, rather our Code is very much static in nature, we can proceed with ahead-of-time compilation.
We need to be sure while taking this approach is that the ahead-of-time compilation should provide us the same output as we get from Java virtual machine. This is helpful for the embedded system where dynamic linking or extension is not necessary. This can be achieved by putting the compiled executable file to a ROM portion of the embedded system.
Ahead-of-time compilation can help the Java desktop application which is stand-alone in nature.
Java supports TCP/IP and URL by default. Java also supports Remote Procedure Call(RPC) like feature via RMI (Remote Method Invocation )
The perforce gets a major hit and managing them becomes more difficult when we create a distributed system where objects may move from a virtual machine to others. While this type of object-oriented network programming is the basic backbone of Java’s architecture, managing performance is an issue. We can design our system the way we want (like minimizing network traffic, select the best algorithm or any other techniques, performance tuning).
As long as we are able to address the speed issue successfully, we can use the java language and gets Java’s potential benefits. (productivity, program robustness for end-user).
Java treats all Java classes as a separate unit of execution. For increasing efficiency, A class is loaded by JVM only. When it is needed. This runtime binding makes Java more dynamic.
No Pointers any more
Because of Java programs are dynamically linked, the references from one class file to another are symbolic. In a statically linked executable, reference between classes are direct pointers or offsets. Inside a java class file, a reference to another class uses string to represent other class.
If the reference is for the field, the fields name and descriptor need to be specified. For method, method’s name and description (return type, argument) need to be mentioned.
Java class files maintain symbol references to the fields and methods of other classes along with the symbolic references to their own fields and methods. Java class file may also contain debug information (name and type of local variables). These symbol information and close relationship with the bytecode instruction set along with Java code references make the decompile process of a class file to its source file. This makes the proprietary source to go public.
On the other hand, decompilation of the statically linked binary executable is very difficult as the symbolic information (class, field, method, local variables) are missing and they are heavily optimized.
However, we can obfuscate our classes that intern changes the names of classes, alter fields, methods and local variables. Obfuscate, does not change the execution of operations of the code. Once we obfuscate a Java code class files, can be decompiled but they do not yield any meaningful information.