Java class sensitivity

If you write two open Java classes with the same name case insensitive in different directories, then both classes cannot be used at run time. (I tested this on Windows, Mac, and Linux with several versions of JSM HotSpot. I won’t be surprised if there are other JVMs where they can be used at the same time.) For example, if I create a class named a and one named a like this:

 // lowercase/src/testcase/a.java package testcase; public class a { public static String myCase() { return "lower"; } } // uppercase/src/testcase/A.java package testcase; public class A { public static String myCase() { return "upper"; } } 

Three eclipse projects containing the code above are available from my site .

If I try to call myCase in both classes, for example:

 System.out.println(A.myCase()); System.out.println(a.myCase()); 

Typechecker error, but when I run the class file, generating the code directly above, I get:

Exception in thread "main" java.lang.NoClassDefFoundError: testcase / A (invalid name: testcase / a)

In Java, names are generally case sensitive. Some file systems (like Windows) are case insensitive, so I'm not surprised how this happens, but it seems wrong. Unfortunately, the Java specifications are strangely unspecific which classes are visible. The Java Language Specification (JLS), Java SE 7 Edition (section 6.6.1, p. 166) states:

If a class or interface type is declared publicly available, any code can be assigned to it, provided that the compilation unit (Β§7.3) in which it is declared is observable.

In Section 7.3, JLS defines the observability of a compilation unit in extremely vague terms:

All compilation units of the predefined java package and its subpackages lang and io are always observable. For all other packages, the host system determines which compilation units are observable .

The Java virtual machine specification is also vague (section 5.3.1):

The following steps are used to load and thereby create a nonarray class or C interface, denoted by [binary name] N, using the bootstrap class loader [...] Otherwise, the Java virtual machine passes argument N to the bootstrap class loader method to find the intended representation C depending on the platform.

All this leads to four questions in decreasing order of importance:

  • Are there any guarantees as to which classes are loaded by the default class loader in each JVM? In other words, can I implement a valid but degenerate JVM that will not load any classes other than those specified in java.lang and java.io?
  • If there are any guarantees, the behavior in the above example violates the guarantee (i.e. is the behavior an error)?
  • Is there a way to make HotSpot a and a boot at the same time? Will a custom classloader write?
+46
java jvm jls
Jun 05 2018-12-12T00:
source share
3 answers
  • Are there any guarantees as to which classes are loaded by the bootstrap class loader in each JVM?

The main bits and pieces of the language, as well as supporting implementation classes. The inclusion of any class that you write is not guaranteed. (A regular JVM loads your classes into a separate classloader from the bootstrap, and in fact a regular bootloader loads its classes from the JAR in normal mode, as this provides a more efficient deployment than the large old directory structure full of classes.)

  • If there are any guarantees, the behavior in the above example violates the guarantee (i.e. is the behavior an error)?
  • Is there a way to make the "standard" JVM load a and A at the same time? Will a custom classloader write?

Java loads classes by matching the fully qualified class name with the file name, which it then looks for in the class path. So testcase.a goes into testcase/a.class , and testcase.a goes into testcase/a.class . Some file systems mix these things and may serve another when requested. Others understand this correctly (in particular, the variant of the ZIP format used in JAR files is completely case-sensitive and case-sensitive). Java cannot do anything (although the IDE can process it for you, saving .class files from the native FS, I don’t know if this is really happening, and the javac JDK is definitely not that smart).

However, this is not the only point that should be noted here: class files are known inside the class they are talking about. The absence of the expected class from the file simply means that the download failed, which led to the resulting NoClassDefFoundError . You had a problem (improper deployment, at least in a sense) that was detected and resolutely. Theoretically, you could build a class loader that could handle such things while continuing to search, but why bother? Putting class files inside the JAR will fix things much more reliably; they are processed correctly.

More generally, if you run into this problem a lot, take a Unix with a case-sensitive file system to build in Unix (a CI system such as Jenkins is recommended) and find which developers call the classes using just random differences and make them stop as it is very confusing!

+18
Jun 05 '12 at 18:10
source share
β€” -

A subtle subtle explanation leaves little to be added, but let me briefly talk about this phrase:

... Java classes with the same case-insensitive name ...

Names and strings in general never on their own are case sensitive, this is just the interpretation that can be. Secondly, Java does not make such an interpretation.

So, the correct wording of what you had in mind would be:

... Java classes whose file representations on the case-insensitive file system have the same name ...

+1
Jun 06 2018-12-06T00:
source share

Do not think about folders.

Use explicit different namespaces ("packages") for your classes, and perhaps use folders to match your classes.

When I mention "packages", I do not mean the "* .JAR" files, but only the concept:

 package com.mycompany.mytool; // "com.mycompany.mytool.MyClass" public class MyClass { // ... } // class MyClass 

If you do not specify a package for your code, java-tools (compiler, IDE, any) assume to use the same global package for everyone. And, in the case of several similar classes, they have a list of folders where to look.

Packages are like β€œvirtual” folders in your code and apply to all your packages in your classpath or Java installation. You can have several classes with the same ID, but if they are in another package and you specify which package to look for, you will not have problems.

Only my 2 cents, for your cup of Java coffe

-2
Jun 05 2018-12-12T00:
source share



All Articles