Javaに対する批判
Javaはセキュリティと移植性を重視して設計されたので、Javaではマシンアーキテクチャとアドレス空間への直接アクセスをサポートしていない。スキャナ(デジタルカメラ、オーディオレコーダ、ビデオキャプチャ)ないし実質的に直接メモリ空間の制御(一般的に、ドライバインストールを必要とするハードウェアやそれらの部品)を必要とする特定の一部のハードウェアを動かすことはJavaでは容易に実現できないことを意味する。この問題の実例はJavaのバージョン1.0で見られた。様々なプリンタドライバへのインタフェースコードがこの初期のJava実行環境に含まれず、プリンタへのアクセスが可能でなかった。
Javaは、Java仮想マシン (JVM) の上部で動くバイトコード言語である。異なるプラットフォームで実行できる能力と言語の互換性は、最終的にはJVM実装の安定性とJVMのバージョンに依存している。Javaは非常に様々なシステム上で動くとうたわれているが、最新のJVM(とJRE)はWindows、Linux、Solaris対応だけ活発に更新されている状況である。HP-UX(Java for HP-UXなど)とIBM (for MVS、AIX、OS/400) は、それぞれのプラットフォームファミリー独自の実装を提供するが、必ずしも最新のサン・マイクロシステムズのリリースを反映していない。他のプラットフォームにおけるJVM実装も、たいてい今後も続くが、時々一般の実装例よりも何年か何ヶ月か遅れるので、互換性問題が生じる。具体的な例を示すと、Java 2 Platform Standard Edition 1.5 (J2SE 1.5) をサン・マイクロシステムズがリリースしたのは2004年9月30日だが、Mac OS X用J2SE 1.5をAppleが公開したのは2005年3月であり、5か月余りの差が生じている。
Javaの設計者らは、現在他の言語にあるいくつかの機能(多重継承、演算子多重定義、タプルなど)を実装しないことを決めた。
総称型(ジェネリクス)がJava 5.0に導入されたとき、すでにJavaにはクラスの大規模な枠組みがあった(それらの多くはすでに非推奨となっていた)、そして後方互換性を保つため、総称型の実装方法として既存のクラスを維持することを可能にする(コンパイル時の)型消去(型削除、type erasure)が選ばれた。これは、他の言語と比べると、総称型の導入によって提供される機能を限定してしまう結果になった。
Javaのプリミティブ型はオブジェクトではない。プリミティブ型は値への参照ではなく値そのものをスタック領域に保持している。この設計選択はパフォーマンス上の理由により行われた。このためJavaは純粋なオブジェクト指向言語と見なされていない。またこのことによりリフレクションがより複雑になっている。