简体   繁体   English

Java RMI异常错误

[英]Java RMI Exception Error

I am just starting to learn RMI and JFrame and I have been stuck on an exception for a bit. 我刚刚开始学习RMI和JFrame,并且在异常中停留了一段时间。 I'm writing a client/server interaction that will access stock information from yahoo's database. 我正在编写一个客户端/服务器交互,它将从yahoo的数据库访问股票信息。

Here's my code: 这是我的代码:

package stockquote;

public class StockQuote{

    public double currentPrice, priceChange, dailyLow, dailyHigh;

    public StockQuote(double price, double change, double low, double high){
        currentPrice = price;
        priceChange = change;
        dailyLow = low;
        dailyHigh = high;
    }

    public StockQuote(){
        currentPrice = 0;
        priceChange = 0;
        dailyLow = 0;
        dailyHigh = 0;
    }
}



package stockquote;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface StockQuoteInterface extends Remote{
    public StockQuote getQuote(String symbol) throws RemoteException;
}



package stockquote;

import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.UnicastRemoteObject;

import java.io.*;
import java.util.Properties;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.rmi.RemoteException;
import java.util.*;

public class StockQuoteServer implements StockQuoteInterface{

    public StockQuote getQuote(String symbol) throws RemoteException{

        StockQuote information = new StockQuote();

        try{
            URL url = new URL("http://download.finance.yahoo.com/d/quotes.csv?s=" + symbol + "&f=l1c1hg");
            URLConnection conn = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String quoteString = in.readLine();
            in.close();

            String[] data = quoteString.split(",");

            information.currentPrice = Double.parseDouble(data[0]);
            information.priceChange = Double.parseDouble(data[1]);
            information.dailyHigh = Double.parseDouble(data[2]);
            information.dailyLow = Double.parseDouble(data[3]);

        }catch(Exception e){
            e.printStackTrace();
        }

        return information;
    }

    public static void main(String[] args) throws Exception {
        try {
            StockQuoteServer obj = new StockQuoteServer();
            StockQuoteInterface stub = (StockQuoteInterface) UnicastRemoteObject.exportObject(obj, 0);

            Registry registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);

            registry.rebind("StockQuoteServer", stub);   
            System.err.println("StockQuote Server is running.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}



package stockquote;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.rmi.*;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.*;

public class StockQuoteClient extends JFrame implements ActionListener{
    private static final long serialVersionUID = 1L;

    private static StockQuoteInterface stockQuote;

    private JTextField symbolField = new JTextField(10);
    private JTextField currentPriceField = new JTextField(10);
    private JTextField priceChangeField = new JTextField(10);
    private JTextField dailyHighField = new JTextField(10);
    private JTextField dailyLowField = new JTextField(10);
    private JButton lookup = new JButton("Lookup");

    public StockQuoteClient() throws RemoteException{

        try {
            Registry registry = LocateRegistry.getRegistry("localhost");
            stockQuote = (StockQuoteInterface) registry.lookup("StockQuoteServer");

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(0);
        }

        this.setLayout(new GridLayout(0,1));
        JPanel symbolPanel = new JPanel();
        symbolPanel.add(new JLabel("Stock Symbol: "));
        symbolPanel.add(symbolField);
        this.add(symbolPanel);

        this.setLayout(new GridLayout(0,1));
        JPanel fieldsPanel = new JPanel();
        fieldsPanel.add(new JLabel("Current Price: "));
        fieldsPanel.add(currentPriceField);
        fieldsPanel.add(new JLabel("Price Change: "));
        fieldsPanel.add(priceChangeField);
        fieldsPanel.add(new JLabel("Daily High: "));
        fieldsPanel.add(dailyHighField);
        fieldsPanel.add(new JLabel("Daily Low: "));
        fieldsPanel.add(dailyLowField);
        this.add(fieldsPanel);

        JPanel lookupButtonPanel = new JPanel();
        lookupButtonPanel.add(lookup);
        this.add(lookupButtonPanel);

        lookup.addActionListener(this);

        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(240, 350);
        this.setVisible(true);

    }

    public void actionPerformed(ActionEvent e){ 
        StockQuote quoteInfo = new StockQuote();

        Object source = e.getSource();

        try{
            if(source == lookup){
                String symbol = symbolField.getText().trim();
                quoteInfo = stockQuote.getQuote(symbol);
                if(quoteInfo.currentPrice == 0.0){
                    currentPriceField.setText("Error");
                    priceChangeField.setText("Error");
                    dailyHighField.setText("Error");
                    dailyLowField.setText("Error");
                }else{
                    currentPriceField.setText(Double.toString(quoteInfo.currentPrice));
                    priceChangeField.setText(Double.toString(quoteInfo.priceChange));
                    dailyHighField.setText(Double.toString(quoteInfo.dailyHigh));
                    dailyLowField.setText(Double.toString(quoteInfo.dailyLow));
                }
            }
        }catch(RemoteException ex){
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) throws RemoteException{
        /*StockQuote ggg = new StockQuote();

        Scanner keyboard = new Scanner(System.in);
        System.out.println("Enter a symbol: ");
        String symbol = keyboard.nextLine();

        ggg = stockQuote.getQuote(symbol);

        System.out.println(ggg.currentPrice);*/
        new StockQuoteClient();
    }

}

And here is the exception I am receiving. 这是我收到的例外。

Exception in thread "main" java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: stockquote.StockQuote
at sun.rmi.server.UnicastRef.invoke(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(Unknown Source)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(Unknown Source)
at com.sun.proxy.$Proxy0.getQuote(Unknown Source)
at stockquote.StockQuoteClient.main(StockQuoteClient.java:101)
Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: stockquote.StockQuote
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source)
... 5 more
Caused by: java.io.NotSerializableException: stockquote.StockQuote
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at sun.rmi.server.UnicastRef.marshalValue(Unknown Source)
at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at sun.rmi.transport.Transport$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(Unknown Source)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$256(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)

The root cause reported in the stack trace is 堆栈跟踪中报告的根本原因是

java.io.NotSerializableException: stockquote.StockQuote java.io.NotSerializableException:stockquote.StockQuote

Evidently you have an instance of a class named stockquote.StockQuote in the object graph of an object you are trying to serialize, but that class is not serializable. 显然,您要序列化的对象的对象图中有一个名为stockquote.StockQuote的类的实例,但是该类不可序列化。

From other parts of the stack trace, it appears that the serialization attempt is related to an attempt to invoke a remote method -- RMI relies on Java serialization deliver arguments to remote methods and to receive return values from them. 从堆栈跟踪的其他部分来看,似乎序列化尝试与调用远程方法有关— RMI依赖Java序列化将参数传递给远程方法并从远程方法接收返回值。

Certainly stockquote.StockQuote must implement java.io.Serializable if you want to be able to pass or return instances over RMI. 当然,如果您希望能够通过RMI传递或返回实例, stockquote.StockQuote必须实现java.io.Serializable That might or might not be sufficient to actually serialize instances, however, depending on the class's members. 但是,这可能或可能不足以实际序列化实例,具体取决于类的成员。

The stacktrace tells you exactly what the error is. stacktrace会告诉您确切的错误是什么。 You need make StockQuote impement Serializable , because RMI uses Java's serialization mechanism to transmit data (such as method arguments and return value) over the wire. 您需要使StockQuote impement成为Serializable ,因为RMI使用Java的序列化机制来通过网络传输数据(例如方法参数和返回值)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM