Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Effective Ways to Implement and Use the Singleton Design Pattern

Yolande Poirier-OracleJul 30 2015 — edited Oct 6 2015

by Payene Denis Kombate

Explore the pros and cons of various ways to implement the Singleton pattern, and learn how to use the pattern to create a database connection whose parameters can be updated after a Java application has been compiled.

This article discusses the following three topics about the Singleton design pattern:

  • The different ways to implement the Singleton pattern
  • How to create a class for a database connection using the Singleton pattern
  • How to update the class parameters for a database connection after the application has been compiled

Before delving into the subject, let's define the Singleton pattern.

The Singleton pattern is one of many design patterns. Its unique characteristic is that it allows the existence of only and only one instance of a class. To ensure the uniqueness of a singleton, it is very important to control the process of its instantiation. Declaring the constructor as private prevents any external script from using the keyword new to directly create an instance of the singleton class.

As a result, any code wanting to get an instance of the singleton should pass a specific method named getInstance instead of the usual constructor. This method should be static, and it is the method that can directly execute the instantiation of the singleton using the keyword new.

Different Ways to Implement a Singleton Class

Now, let's explore the various ways to implement a singleton.

Minimal Singleton

Listing 1 shows a minimal version of a singleton:

public class JavaSingleton {

     private JavaSingleton() {
        /* the body of the constructor here */
     }

     /* pre-initialized instance of the singleton */
     private static final  JavaSingleton INSTANCE = new JavaSingleton();

     /* Access point to the unique instance of the singleton */
     public static JavaSingleton getInstance() {
        return INSTANCE;
     }
}

Listing 1. Minimal singleton

The class in Listing 1 seems correct, but it has some imperfections because it immediately loads the instance of the class when the application starts even if the instance is not needed. In some cases, the best approach is to load the instance of the class in memory only when the method getInstance is called. There is an approach called lazy loading that allows a late loading of the instance of a singleton in memory.

Lazy-Loading Singleton

Listing 2 shows the singleton class declaration with lazy loading.

public class JavaSingleton {
  private JavaSingleton() {
        /* the body of the constructor here */
    }
    /* declaration of instance of the singleton */
    private static JavaSingleton INSTANCE;

    /* Access point to the unique instance of the singleton */
    public static JavaSingleton getInstance() throws Throwable {
        if (INSTANCE == null) {
            INSTANCE = new JavaSingleton();
        }
        return INSTANCE;
    }
}

Listing 2. Lazy-loading singleton

The code in Listing 2 seems correct, but it's inappropriate in a multithreaded environment and is susceptible to returning more than one instance of the singleton if the method getInstance() is not protected by a synchronization.

Synchronized Singleton

Listing 3 shows a synchronized singleton class:

public class JavaSingleton {
     /* Private constructor     */
     private JavaSingleton() {
           /* the body of the constructor here */
     }

     /* pre-initialized instance of the singleton */
     private static JavaSingleton INSTANCE;

     /* Access point to the unique instance of the singleton */
     public static JavaSingleton getInstance() {
       if (INSTANCE == null){
          synchronized(JavaSingleton.class){
               INSTANCE = new JavaSingleton();
          }
       return INSTANCE ;
       }
     }
}

Listing 3. Synchronized singleton

Two threads can enter the if block at the same time when INSTANCE is null. The first thread enters the synchronized block to initialize INSTANCE while the second thread is blocked. When the first thread gets out of the synchronized block, the second one, which was blocked, can then enter the synchronized block. But when the second thread enters the synchronized block, it does not verify whether INSTANCE is null before initializing it.

In this case, the simplest solution would be to synchronize the get method instance, but this would affect the performance of the program. If the singleton is called frequently in the program, this will make the program work very slowly.

So the way to resolve the problem is to have a second verification in the synchronized block. There is an idiom that does this verification: double-checked locking.

Double-Checked Locking Singleton

Listing 4 shows a singleton class declaration with double-checked locking.

public class JavaSingleton {
     /* Private constructor     */
     private JavaSingleton() {
        /* the body of the constructor here */
     }

     /* pre-initialized instance of the singleton */
     private static JavaSingleton INSTANCE ;

     /* Access point to the unique instance of the singleton */
     public static JavaSingleton getInstance() {
        if (INSTANCE == null){
            synchronized(JavaSingleton.class){
               if(INSTANCE == null){
                    INSTANCE = new JavaSingleton;
               }
            }
            return INSTANCE ;
        }
     }
}

Listing 4. Singleton class declaration with double-checked locking

Intuitively, this algorithm seems like an effective solution to the problem. However, it raises subtle and difficult-to-trace problems. Consider the following sequence of events.

Thread A notices that the shared variable is not initialized. So it acquires the lock and begins to initialize the variable.

Because of the semantics of the programming language, the code generated by the compiler has the right to modify the shared variable before thread A's variable initialization has completed, so the reference variable is a partially initialized object (for example, because the thread begins to allocate memory and places the reference to the allocated memory block in the variable before finally calling the constructor, that will initialize the memory block).

Thread B notices that the shared variable has been initialized (or at least seems to be initialized), and it returns its value immediately without attempting to acquire a lock. If, then, the shared variable is used before thread A has had time to complete its initialization, the program is likely to crash.

One of the dangers of double-checked locking is that often it will appear to work. This depends on the compiler and how threads are scheduled by the operating system, along with other data-access competition management mechanisms. Reproducing the cause of a crash can be difficult, because crashes are highly unlikely when the code is running in a debugger. The use of double-checked locking must, therefore, be limited as much as possible.

Volatile Singleton

The volatile reserved word (see Listing 5) provides a solution to this problem by ensuring that different threads correctly handle concurrent access to the single instance of a singleton. However, this access security has a price: accessing a volatile variable is less efficient than accessing a normal variable.

Note: This functionality has been available since JDK 1.0, but it is deprecated now.

/* This doesn't work with Java 1.4 or earlier*/

class JavaSingleton {
     /* Private constructor     */
     private JavaSingleton() {
        /* the body of the constructor here */
     }

     /* instance of the singleton declaration */
     private volatile  JavaSingleton INSTANCE ;

     /* Access point to the unique instance of the singleton */
     public static JavaSingleton getInstance() {
        if (INSTANCE == null){
           synchronized(JavaSingleton.class){
              if(INSTANCE == null){
                 INSTANCE = new JavaSingleton;
              }
           }
        return INSTANCE ;
        }
     }
}

Listing 5. Example of code that uses volatile

Many versions of double-checked locking that do not use explicit synchronization or the volatile variable have been proposed. Apart from those based on the keyword enum pattern, all have proved to be incorrect.

Class Holder Singleton

The last technique of creating a singleton that we'll talk about is the class holder. It relies on the use of a private inner class, which is responsible for instantiating the single instance of the singleton, as shown in Listing 6.

public class JavaSingleton {
     /* Private constructor     */
     private JavaSingleton() {
        /* the body of the constructor here */
     }

     /* Access point to the unique instance of the singleton */
     public static JavaSingleton getInstance() {
         return INSTANCE;
     }

     private static class JavaSingletonHolder{
     private static final Singleton INSTANCE = new JavaSingleton()
     }
}

Listing 6. Example of a private inner class that instantiates a singleton

This type of singleton is recommended in any multithreaded environment.

Now let's explore the second point of this article.

How to Create a Database Connection Class Using a Singleton

A database connection class can be created by extending the Java Persistence API (JPA) or by creating a simple class with a method that returns the connection statement. Those who use JPA need not be concerned with this part of the article, because with JPA the persistence is based on the Singleton pattern.

From here to the end of the article the singleton class JavaSingleton will be called DbSingleton (this name is more appropriate for a database connection singleton).

Listing 7 shows a class that ensures that there will never be two instances of the database connection.

public class DbSingleton {
    private static String db_url;
    private static String db_port;
    private static String db_name;
    private static String db_user;
    private static String db_password;
    private static Statement connection;

    private DbSingleton() {
/* 
       *Default database parameters 
*/
        db_url = "jdbc:mysql://localhost";
        db_port = "3306";
        db_name = "mysql";
        db_user = "root";
        db_password = "admin";
/* Creation of an instance of the connection statement*/
        connection = setConnection();
    }
/* Private method charge to set the connection statement*/
    private static Statement setConnection() {
        try {
            String url = "" + db_url + ":" + db_port + "/" + db_name + "";
            java.sql.Connection conn = DriverManager.getConnection(url, db_user, db_password);

            //Creation of the Statement object
            java.sql.Statement state = conn.createStatement();
            return (Statement) state;
        } catch (SQLException ex) {
            Logger.getLogger(DbSingleton.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

/* Private inner class responsible for instantiating the single instance of the singleton */
    private static class DbSingletonManagerHolder {
        private final static DbSingleton instance = new DbSingleton();
    }

    /**
     * @return
Public method, which is the only method allowed to return an instance of 
the singleton (the instance here is the database connection statement)
     */
    public static DbSingleton getInstance() {
        try {
            return DbSingletonManagerHolder.instance;
        } catch (ExceptionInInitializerError ex) {

        }
        return null;
    }
    public static Statement getStatement() {
        return connection;
    }
}

Listing 7. Class that prevents two instances of the database connection

With this class, you can be sure there will never be two instances of the database connection. The way to use the database statement is shown in Listing 8:

/* Creation of the statement instance */
DbSingleton single = DbSingleton.getInstance();
Statement state = DbSingleton.getStatement();
/* put your SQL code in the variable sqlString */
String sqlString = "" ;
ResultSet result = state.executeQuery(sqlString);

Listing 8. Example of how to use the database connection

Now let's examine the last topic of this article.

How to Update the Parameters for a Database Connection After the Application Has Been Compiled

When the application will be compiled it will be impossible to change the database parameters manually directly in the source code, but we'll see a trick now for how to do this programmatically.

First, in the application, we create a form into which the new database parameters will be typed. The form should have the following fields:

  • Server address
  • Server port
  • Database username
  • Database password
  • Database name

When a user submits this form, the parameters that were typed in should be stored in an XML or plain text file of your choice.

Add the Parameters class shown in Listing 9 to manage the updating of the database parameters.

public class Parameters {
    private static String url;
    private static String port;
    private static String dbName;
    private static String user;
    private static String pass;
    private static final String storeFilePath = "/home/path/to/txt/file";
    public Parameters() {
        String parameters[];
        try {
            parameters = txtReader();
            url = parameters[0]; port = parameters[1]; dbName = parameters[2];
                  user = parameters[3]; pass = parameters[4];
        } catch (IOException ex) {
            Logger.getLogger(Parameters.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    /* This method returns an array containing the database parameters in the following order: url,port,dbname,user,pass */
    public static String[] txtReader() throws IOException {
        BufferedReader read;
        String line = "";    String[] params = null;
        try {
            read = new BufferedReader(new FileReader(storeFilePath));
            line = line + read.readLine();
            /* Split the content of the file*/
            params = line.split(";");
        } catch (NullPointerException a) {
            System.out.println("Error : pointer null");
        } catch (IOException a) {
            System.out.println("I/O Problem");
        } finally {
            System.out.println("I/O Problem");
        }
        return params;
    }
    public void txtWriter(String user, String pass, String address, String port, String dbname) {
        /* Specify the path to the file where the database parameters will be stored */
        String path = storeFilePath;
        final File file = new File(path);
        try {
            // Creation of the file
            file.createNewFile();
            // creation of the writer
            final FileWriter writer = new FileWriter(file);
            try {
                /*Save database parameters, separated by a semi-colon (;), in a text file*/
                writer.write(address + ";" + port + ";" + dbname + ";" + user + ";" + pass);
            } finally {
                // Whatever happens, the file should be closed
                writer.close();
            }
        } catch (Exception e) {
            System.out.println("Impossible to create the file");
        }
    }

    public static String getUrl() {
        return url;
    }
    public static String getPort() {
        return port;
    }
    public static String getDbName() {
        return dbName;
    }
    public static String getUser() {
        return user;
    }
    public static String getPass() {
        return pass;
    }
    public void setUrl(String dburl) {
        url = dburl;
    }
    public void setPort(String dbport) {
        port = dbport;
    }
    public void setDbName(String db_name) {
        dbName = db_name;
    }
    public void setUser(String dbuser) {
        user = dbuser;
    }
    public void setPass(String dbpass) {
        pass = dbpass;
    }
}

Listing 9. Code for managing the updating of the database parameters

Now we will update the DbSingleton by calling the method getParameters() and overriding the values of the default parameters with values that we get from the external file.

First, update DbSingleton by overriding the private constructor using the script shown in Listing 10:

private DbSingleton() {
/* 
   * Overriding database parameters 
*/
        Parameters params = new Parameters() ;
        db_url = params.getUrl();
        db_port = params.getPort() ;
        db_name = params.getName() ;
        db_user = params.getUser() ;
        db_password = params.getPass() ;
/* Creation of an instance of the connection statement*/
        connection = setConnection();
}

Listing 10. Script for overriding the private constructor

To override the current database parameters, the current instance of DbSingleton should be cleared. To do this you might think of setting INSTANCE to null, but this will never work because INSTANCE is a final variable so no assignment could ever be done to it.

The way to override the singleton very simply is to programmatically restart the application and create a new instance of DbSingleton with the new database parameters.

First, update DbSingleton to add the class shown in Listing 11 to make your application programmatically restartable.

public class Restarter {
    /**
     * Sun property pointing the main class and its arguments. Might not be
     * defined on non-Java HotSpot VM implementations.
     */
    public static final String SUN_JAVA_COMMAND = "sun.java.command";
    /**
     * Restart the current Java application
     *
     * @param runBeforeRestart some custom code to be run before restarting
     * @throws IOException
     */
    public static void restartApplication(Runnable goRestart) throws IOException {
        try {
            // Java binary
            String java = System.getProperty("java.home") + "/bin/java";
            /*  Java virtual machine arguments */
            List<String> jvmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments();
            StringBuffer jvmArgsOneLine = new StringBuffer();
            for (String arg : jvmArgs) {
              /* if it's the agent argument it is ignored; otherwise; 

              the address of the old application and the new one will be 
              in conflict
             */
                if (!arg.contains("-agentlib")) {
                    jvmArgsOneLine.append(arg);
                    jvmArgsOneLine.append(" ");
                }
            }
            // init the command to execute
            final StringBuffer cmd = new StringBuffer("" + java + " " + jvmArgsOneLine);

            // program main and program arguments
            String[] mainCommand = System.getProperty(SUN_JAVA_COMMAND).split(" ");
            // if program has a JAR as main
            if (mainCommand[0].endsWith(".jar")) {
                // if it's a JAR, add -jar mainJar
                cmd.append("-jar " + new File(mainCommand[0]).getPath());
            } else {
            // else if it's a class, add the classpath and mainClass to the command
                cmd.append("-cp " + System.getProperty("java.class.path") + " " + mainCommand[0]);
            }
            /* finally add program arguments */
            for (int i = 1; i < mainCommand.length; i++) {
                cmd.append(" ");
                cmd.append(mainCommand[i]);
            }
            /* execute command in shutdown hook to be sure that all the 
             resources have been disposed before restarting the application */
            Runtime.getRuntime().addShutdownHook(new Thread() {
                @Override
                public void run() {
                    try {
                        Runtime.getRuntime().exec(cmd.toString());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
            if (goRestart != null) {
                goRestart.run();
                System.exit(0);
            }
        } catch (Exception e) {
            // something went wrong
            throw new IOException("Error while trying to restart the application", e);
        }
    }
}

Listing 11. Class that makes the application programmatically restartable

After adding the class shown in Listing 11, connect the script shown in Listing 12 to the Submit button of the form we previously discussed.

/* 
* Here, put code to recover the database parameters from the form
* into the following variables:
* dbUrl, dbName, dbPort, dbAddress, dbPassword
*/

Parameters param = new Parameters() ;
params.txtWriter(dbUrl, dbName, dbPort, dbAddress, dbPassword) ;
 Runnable r = new Runnable() {
            @Override
            public void run() {
                JOptionPane.showMessageDialog(null, "Application restarted successfully ", 
                "Restarting", JOptionPane.INFORMATION_MESSAGE);
            }

 };

 try {
            restartApplication(r);
 } catch (IOException ex) {
            Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
 }

Listing 12. Script for getting database parameters from the form

See Also

About the Author

Payene Denis Kombate is a freelance PHP, Java, and mobile developer with four years of experience. He lives in Togo (West Africa), writes a blog (in French), and can be reached on Facebook, on Google+, and via e-mail.

Join the Conversation

Join the Java community conversation on Facebook, Twitter, and the Oracle Java Blog!

Comments

Steffen Moser
Answer

You could have a look at the Github repository: https://github.com/oracle/solaris-userland/. You should find the build environment for Firefox there: https://github.com/oracle/solaris-userland/tree/master/components/desktop/firefox

Kind regards,
Steffen

Marked as Answer by 993047 · Sep 27 2020
993047

Thanks very much, that sure looks like what I needed.  Just one question - maybe I missed it in the documentation but are these things meant to be run in Solaris 11.4 or in Linux for cross-compilation?

Steffen Moser

They are meant to be run in Solaris 11.4. I haven't compiled Firefox, yet. Use "gmake" not "make". You need a lot of build tools, e.g. Developer Studio and the GCC compiler.

993047

OK great.  I'll give it a shot.

993047

Well this is odd.  Things were going fine until I got to this:

michele@hemlock:/scratch/clone/components$ gmake download

Generating component list...

/bin/bash: /scratch/clone/tools/userland-components: /usr/bin/python3.7: bad interpreter: No such file or directory

/bin/bash: /scratch/clone/tools/userland-components: /usr/bin/python3.7: bad interpreter: No such file or directory

Generating component dependencies...

(I watched /scratch/clone/sparc during this.  It created two empty files called components.mk and depends.mk.  After three hours of waiting, I hit ctrl-C)

^Cgmake: *** Deleting file '/scratch/clone/sparc/depends.mk'

michele@hemlock:/scratch/clone/components$

I checked and indeed I do not have python 3.7.  Python 3.7 is in the components directory but apparently you need python 3.7 to make python 3.7.

And this didn't work:

root@hemlock:/scratch/clone/sparc# pkg install python-37

pkg install: The following pattern(s) did not match any allowable packages.  Try

using a different matching pattern, or refreshing publisher information:

    python-37

root@hemlock:/scratch/clone/sparc#

And I haven't been able to find it anywhere else.

So I'm stuck.  ???

UPDATE

I installed python 3.7 directly from python.org and got gmake download to start.  Now I'm getting this:

Source http://userland.us.oracle.com/source-archives/a2ps-4.14.tar.gz...

    downloading... failed

Can't open url http://userland.us.oracle.com/source-archives/a2ps-4.14.tar.gz

<urlopen error [Errno 8] node name or service name not known>

...

Source https://01.org/sites/default/files/page/pmtools-20071116.tar.gz...

    downloading... failed

Can't open url https://01.org/sites/default/files/page/pmtools-20071116.tar.gz

HTTP Error 404: Not Found

Cannot download the archives! Terminating...

A visit to userland.us.oracle.com confirms that this site is 404.

So does any of this git download stuff work?

Steffen Moser

Unfortunately, the download scripts link to an internal Oracle server which is not available from outside. If you fetch the required files from their original sources and place them in the packages' main directories, the scripts will be typically satisfied.

Compiling such a big tool as Mozilla Firefox is quite a large piece of work and might require a lot of prerequisites. Typically, you don't have to compile everything, so you could start the "gmake build" also in the Firefox subdirectory and find which packages are missing. You could then compile the missing ones explicitly. I've used the build scripts myself to build newer versions of PHP and SVN, before, but I've never tried to compile such a large tool like Firefox.

Maybe you could have a look at http://sfe.opencsw.org/ and find if they provide community builds of Firefox. Maybe you could have a look at OmniOS or OpenIndiana and find out whether they come with a more recent version of Firefox, though I have not checked it myself.

993047

Thanks for the suggestions but I've been there, failed to do that.  CSW only offers old versions of FF.  OI does have FF 60 but when I tried to install that I got

root@hemlock:~/Downloads# pkg install //openindiana.org/web/browser/firefox@60.8.0,5.11-2018.0.0.0:20190713T032125Z

pkg install: The following pattern(s) only matched packages that are not available

for the current image's architecture, zone type, and/or other variant:

    //openindiana.org/web/browser/firefox@60.8.0,5.11-2018.0.0.0:20190713T032125Z

And yet Oracle is offering FF 68.  HOW do they do it???  (BTW, firefox seems to have been quietly removed from solaris userland at some point in the last week.  That's odd...)

Steffen Moser

Hi 993047,

993047 wrote:

Thanks for the suggestions but I've been there, failed to do that. CSW only offers old versions of FF. OI does have FF 60 but when I tried to install that I got

root@hemlock:~/Downloads# pkg install //openindiana.org/web/browser/firefox@60.8.0,5.11-2018.0.0.0:20190713T032125Z

pkg install: The following pattern(s) only matched packages that are not available

for the current image's architecture, zone type, and/or other variant:

//openindiana.org/web/browser/firefox@60.8.0,5.11-2018.0.0.0:20190713T032125Z

Sorry, it was just an idea...

993047 wrote:

And yet Oracle is offering FF 68. HOW do they do it???

I am quite sure that the Oracle team uses the userland repository which I pointed you to. It might be easier for them because they have a build environment that has been updated continuously and step-by-step. This means you'd have to do a lot of bootstrapping work at first. Nevertheless, when I compiled myself my first own PHP versions (I had to upgrade from PHP 5.3 to PHP 5.4 and 5.5 some years ago) using Oracle's build environment, I worked on it for a few days until I had everything running. And I am quite sure that PHP is much easier to handle compared to Firefox when it comes to the prerequisites.

993047 wrote:

(BTW, firefox seems to have been quietly removed from solaris userland at some point in the last week. That's odd...)

I cannot confirm your observation. When looking at https://github.com/oracle/solaris-userland/tree/master/components/desktop/firefox it still seems to be available at the moment.

Kind regards,
Steffen

993047

"Sorry, it was just an idea..."

Oh dear, I hope I didn't give the wrong idea.  I apologize and I greatly appreciate your help.  I'm just frustrated that I keep running into roadblocks.

"I am quite sure that the Oracle team uses the userland repository which I pointed you to."

Thanks - that's an important piece of information.  So then if they're not cross-compiling I won't  waste any more time on that avenue.  I have no problem trying to build a large project.  I've built gcc 7.3, Octave, QEMU, and OpenSCAD for Solaris in the past.  The hard part is just figuring out how to proceed.

"I cannot confirm your observation. When looking at https://github.com/oracle/solaris-userland/tree/master/components/desktop/firefox it still seems to be available at the moment."

Oops! I am very embarrassed.  You are of course absolutely right.  I completely forgot that firefox is in the desktop subdirectory.  I was looking for components/firefox.  Duh!  It's confusing because when you browse their web site, files and directories look the same.  Like I just found that cargo is under components/rust.

Steffen Moser

Hi 993047,

I've tried to do a "gmake build" of Firefox 68.4.1esr on a fully-patches Solaris 11.4 x64 SRU 16 (as I had to start-up my build zone anyway in order to compile an OpenLDAP overlay module which allows the synchronization of Samba and LDAP passwords).

The good news ist: After installing some additional packages (yasm, nodejs, clang, rustc, cargo) the Firefox build actually ran through very fine. Of course, since this is my build zone, I already had some compilation-related packages already installed (e.g. libtool, pkg-config, gcc-9, gcc-7, gcc-5, solarisstudio-124, developerstudio-125, and developerstudio-126).

So I think that by using the repository you are on the right way!

When working on a non-patched Solaris 11.4 installation, the amount of work of providing all requirements is most probably somehow higher. Unfortunately, I do not know which versions of the above-mentioned tools are actually needed in order to build Firefox 68.

Kind regards,
Steffen

993047

Hi Steffen.  That is both encouraging and frustrating.  I Unfortunately, I'm stuck with the free distro of Solaris 11.4 so I can't patch it.  I have this:

Publisher: solaris
Version: 11.4 (Oracle Solaris 11.4.0.0.1.15.0)
Branch: 11.4.0.0.1.15.0

Packaging Date: August 17, 2018 at 12:42:03 AM

I have clang, developerstudio-126

but trying to get yasm got me this:

root@hemlock:~/aoo-4.1.7/main# pkg install yasm

pkg install: The following pattern(s) only matched packages that are not available

for the current image's architecture, zone type, and/or other variant:

        yasm

root@hemlock:~/aoo-4.1.7/main#

For rustc I have mrustc.

but nodejs wouldn't install from pkg install nor from opencsw, although it is in their package list.  So I'm not sure what to do at this point or if it is even possible.  Just wondering - if you actually succeeded in producing a Firefox 68 for SPARC, could I please ask if you might share a copy with me?  I've been trying to get this going for months now with no success.

UPDATE

Oh, I see now.  By your reference to nodejs I assume you built this in x86 Solaris.  I've learned that nodejs is not available for SPARC.  This may not be a game ender though since the Makefile for Firefox in Solaris Userland specifically omits nodejs as a required package if the machine type is sparc.

Steffen Moser

Unfortunately, I don't have access to a patched Solaris 11.4 build host which runs on SPARC architecture. I do only work with x86 Solaris. Sorry!

Kind regards,

Steffen

1 - 12

Post Details

Added on Jul 30 2015
13 comments
46,265 views