• Versioning fun

    From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Mar 27 09:11:43 2024
    A relative little know fact about the JVM is that
    it implicit prefixes class names with the id of
    the classloader.

    That mean that it is possible to load and use
    different version of the same class within the
    same application. If one knows how.

    $ type HasTest.java
    public interface HasTest {
    public void test();
    }
    $ javac HasTest.java
    $ copy X_v1.java X.java
    $ type X.java
    public class X implements HasTest {
    public void test() {
    System.out.printf("Technically I am a %s, but I am version
    1\n", this.getClass().getName());
    }
    }
    $ javac X.java
    $ jar cvf v1.jar X.class
    added manifest
    adding: X.class(in = 588) (out= 376)(deflated 36%)
    $ del X.class;*
    $ copy X_v2.java X.java
    $ type X.java
    public class X implements HasTest {
    public void test() {
    System.out.printf("Technically I am a %s, but I am version
    2\n", this.getClass().getName());
    }
    }
    $ javac X.java
    $ jar cvf v2.jar X.class
    added manifest
    adding: X.class(in = 588) (out= 376)(deflated 36%)
    $ del X.class;*
    $ type TestX.java
    import java.io.File;
    import java.net.URI;
    import java.net.URL;
    import java.net.URLClassLoader;

    public class TestX {
    public static void main(String[] args) throws Exception {
    ClassLoader v1 = new URLClassLoader(new URL[] { (new File("v1.jar")).toURI().toURL() });
    HasTest o1 = (HasTest)Class.forName("X", true, v1).newInstance();
    o1.test();
    ClassLoader v2 = new URLClassLoader(new URL[] { (new File("v2.jar")).toURI().toURL() });
    HasTest o2 = (HasTest)Class.forName("X", true, v2).newInstance();
    o2.test();
    }
    }
    $ javac TestX.java
    $ java "TestX"
    Technically I am a X, but I am version 1
    Technically I am a X, but I am version 2

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Single Stage to Orbit@21:1/5 to All on Wed Mar 27 14:30:59 2024
    On Wed, 2024-03-27 at 09:11 -0400, Arne Vajhøj wrote:
    $ java "TestX"
    Technically I am a X, but I am version 1
    Technically I am a X, but I am version 2

    It is vital to delete the X.class files otherwise it will load that
    instead of the jar files.
    --
    Tactical Nuclear Kittens

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Single Stage to Orbit on Wed Mar 27 11:03:57 2024
    On 3/27/2024 10:30 AM, Single Stage to Orbit wrote:
    On Wed, 2024-03-27 at 09:11 -0400, Arne Vajhøj wrote:
    $ java "TestX"
    Technically I am a X, but I am version 1
    Technically I am a X, but I am version 2

    It is vital to delete the X.class files otherwise it will load that
    instead of the jar files.

    Yes. I should probably have mentioned that explicit.

    Java class loaders are hierarchical and searched top down. The
    default class loader with default classpath of current directory
    is searched before the jar files in the special class loaders.

    $ type Dump.java
    import java.io.File;
    import java.net.URI;
    import java.net.URL;
    import java.net.URLClassLoader;
    import java.util.List;
    import java.util.ArrayList;

    public class Dump {
    private static void dump(String lbl, ClassLoader cl) {
    List<ClassLoader> lst = new ArrayList<ClassLoader>();
    ClassLoader cl1 = cl;
    do {
    lst.add(cl1);
    cl1 = cl1.getParent();
    } while(cl1 != null);
    System.out.printf("Class search path for %s:\n", lbl);
    for(int i = lst.size() - 1; i >= 0; i--) {
    System.out.printf(" %d - %s", lst.size() - i, lst.get(i).getClass().getName());
    if(lst.get(i) instanceof URLClassLoader) {
    System.out.print(" -");
    for(URL url : ((URLClassLoader)lst.get(i)).getURLs()) {
    System.out.printf(" %s", url);
    }
    }
    System.out.println();
    }
    }
    public static void main(String[] args) throws Exception {
    dump("Default", Dump.class.getClassLoader());
    ClassLoader v1 = new URLClassLoader(new URL[] { (new File("v1.jar")).toURI().toURL() });
    dump("V1 library", v1);
    ClassLoader v2 = new URLClassLoader(new URL[] { (new File("v2.jar")).toURI().toURL() });
    dump("V2 library", v2);
    }
    }
    $ javac Dump.java
    $ java Dump
    Class search path for Default:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/
    Class search path for V1 library:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/
    3 - java.net.URLClassLoader - file:/DISK2/ARNE/v1.jar
    Class search path for V2 library:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/
    3 - java.net.URLClassLoader - file:/DISK2/ARNE/v2.jar

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Single Stage to Orbit@21:1/5 to All on Wed Mar 27 16:13:15 2024
    On Wed, 2024-03-27 at 11:03 -0400, Arne Vajhøj wrote:
    It is vital to delete the X.class files otherwise it will load that
    instead of the jar files.

    Yes. I should probably have mentioned that explicit.

    Java class loaders are hierarchical and searched top down. The
    default class loader with default classpath of current directory
    is searched before the jar files in the special class loaders.

    There's the '-cp' to find these classes in other places. My long
    repressed java memories are returning, :(
    --
    Tactical Nuclear Kittens

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Single Stage to Orbit on Wed Mar 27 12:54:16 2024
    On 3/27/2024 12:13 PM, Single Stage to Orbit wrote:
    On Wed, 2024-03-27 at 11:03 -0400, Arne Vajhøj wrote:
    It is vital to delete the X.class files otherwise it will load that
    instead of the jar files.

    Yes. I should probably have mentioned that explicit.

    Java class loaders are hierarchical and searched top down. The
    default class loader with default classpath of current directory
    is searched before the jar files in the special class loaders.

    There's the '-cp' to find these classes in other places. My long
    repressed java memories are returning, :(

    Whatever is specified by -cp get added to the app class loader.

    $ java -cp .:a.jar:/foo/b.jar:/bar/c.jar Dump
    Class search path for Default:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/ file:/DISK2/ARNE/a.jar file:/foo/b.jar file:/bar/c.jar
    Class search path for V1 library:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/ file:/DISK2/ARNE/a.jar file:/foo/b.jar file:/bar/c.jar
    3 - java.net.URLClassLoader - file:/DISK2/ARNE/v1.jar
    Class search path for V2 library:
    1 - sun.misc.Launcher$ExtClassLoader - file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/cldrdata.jar file:/DISK$X86SYS/SYS0
    /SYSCOMMON/openjdk$80/jre/lib/ext/dnsns.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/jaccess.jar file:/DISK$X86SYS/SY
    S0/SYSCOMMON/openjdk$80/jre/lib/ext/localedata.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/nashorn.jar file:/DISK$X8
    6SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunec.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunjce_provider.jar
    fil
    e:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/sunpkcs11.jar file:/DISK$X86SYS/SYS0/SYSCOMMON/openjdk$80/jre/lib/ext/zipfs.jar
    2 - sun.misc.Launcher$AppClassLoader - file:/DISK2/ARNE/ file:/DISK2/ARNE/a.jar file:/foo/b.jar file:/bar/c.jar
    3 - java.net.URLClassLoader - file:/DISK2/ARNE/v2.jar

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Mar 27 21:16:33 2024
    On Wed, 27 Mar 2024 09:11:43 -0400, Arne Vajhøj wrote:

    A relative little know fact about the JVM is that it implicit prefixes
    class names with the id of the classloader.

    I currently have to use Java for a project that involves connecting to an in-house server via HTTPS (modifying an existing app). If there is one
    word that sums up the Java language and APIs, it is “bureaucracy”.

    Consider setting up a TLS/SSL context. In Python, creating the context
    object is one call:

    sctx = ssl.SSLContext(protocol = ssl.PROTOCOL_TLS_CLIENT)

    Loading a private CA cert is one call:

    sctx.load_verify_locations(ca_cert_file)

    Loading a cert and key for client-side authentication is one call:

    sctx.load_cert_chain(client_cert_file, client_key_file)

    But in Java, you first need to create a KeyStore. Load the CA cert via a CertificateFactory and creating a TrustedCertificateEntry. Call the
    factory’s generateCertificate routine to load the client cert. Then go through a whole lot more contortions to load the client key file.

    And then, you have to set up a TrustManagerFactory to create a
    TrustManager, and a KeyManagerFactory to create a KeyManager, so that you
    can load the contents of the KeyStore, via those two separate intermediary objects, into an actual SSLContext for use in HTTPS connections.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)