Java:为什么代码打包成jar文件阻止外部类访问? [英] Java: why code packaged into a jar file prevent external classes from accessing?
问题描述
为什么我的代码打包成一个jar文件阻止外部类访问jar内的类?
编辑:根据请求,堆栈跟踪。
java.lang.NullPointerException
在TestPlugin2 .Main。< init>(Main.java:23)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
在java.lang.reflect.Constructor.newInstance(未知来源)
在java.lang.Class.newInstance0(未知来源)
在java.lang.Class.newInstance(未知来源)
在com.cpcookieman.ph.PluginLoader $ 2.run(PluginLoader.java:74)
在java.lang.Thread.run(未知来源)
编辑2:课程加载代码
String pluginsPath;
if(Main.os.equals(Windows))
{
pluginsPath =C:\\\plugins\\;
}
else
{
pluginsPath =〜/ plugins /;
}
文件文件=新建文件(pluginsPath);
if(!file.exists())
{
System.out.println(DEBUG:Plugin path does not be found!);
}
try
{
URL url = file.toURI()。toURL();
final URL [] urls = new URL [] {url};
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
ClassLoader cl = new URLClassLoader(urls);
Class plugin = cl.loadClass(text +.Main);
plugin.newInstance();
close();
}
** snip catch语句**
}
})。start();
}
** snip catch语句**
插件加载使用它是构造函数,并创建一个要添加到框架内的面板,该框架位于JAR文件中的一个类内。 JAR是主要的应用程序,如果有人对此感到困惑。
我真的不知道你的项目的结构,虽然我已经提供了一个小例子代码,看看,看看。
考虑到我的项目位于 C:\ Mine \JAVA\J2SE\src\testingjar>
这里我的目录结构如下:
testingjar
|
----------------------------------
| | | |
类src manifest.text test.jar(这个.jar我们很快创建)
| |
| (几乎和classes文件夹一样,只有.java文件)
---------------
| |
actualtest test
| |
* .class * .class
我的类将成为.jar的一部分文件,如下所示:
包测试;
import java.awt。*;
import javax.swing。*;
public class CustomPanel扩展JPanel
{
public CustomPanel()
{
setOpaque(true);
setBackground(Color.DARK_GRAY);
JLabel label = new JLabel(
我是Java Swing中的JLabel,JLabel.CENTER);
label.setOpaque(false);
label.setForeground(Color.WHITE);
add(label);
}
@Override
public Dimension getPreferredSize()
{
return(new Dimension(500,300));
}
}
我用以下命令编译了这个类:
C:\Mine\JAVA\J2SE\src\testingjar> javac -d类src\test\CustomPanel.java
现在为JAR文件创建清单文件,其内容如下:
主类:test.CustomPanel
<记住冒号(:)和包名称之间的空格,即test,并在CustomPanel之后,按下键输入并保存文件。
现在创建名为的JAR文件test.jar
,我写了这些命令:
C:\Mine\JAVA\J2SE\src\testingjar> cd类
C:\Mine\JAVA\J2SE\src\testingjar\classes> jar -cfm ..\test.jar ..\manifest.txt test
现在,将使用此.jar文件的类将如下所示:
package actualtest;
import test.CustomPanel;
import java.awt。*;
import javax.swing。*;
public class ActualImplementation
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame(Testing Jar Implementation);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CustomPanel panel = new CustomPanel();
frame.setContentPane(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String ... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ActualImplementation()。createAndDisplayGUI();
}
});
}
}
我编写了这些命令:
C:\Mine\JAVA\J2SE\src\testingjar\classes> cd ..
C:\Mine\JAVA\J2SE\src\testingjar> javac -classpath test.jar -d classes src\actualtest\ActualImplement
ation。 java
现在运行我写这些命令:
C:\Mine\JAVA\J2SE\src\testingjar> cd类
C:\\ \\Mine\JAVA\J2SE\src\testingjar\classes> java actualtest.ActualImplementation
OUTPUT
做出匹配的步骤,可能你会缺少一些东西,因为它在我身边工作正常。
最新编辑:As as ked,我这样做了,而现在的 JFrame
在.jar文件中,而 JPanel
正在使用它。
将成为.jar文件一部分的类如下:
包测试;
import java.awt。*;
import javax.swing。*;
public class CustomFrame extends JFrame
{
public CustomFrame(String title)
{
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
清单的内容。 txt文件将更改如下:
主类:test.CustomFrame
从.jar文件中使用CustomFrame Class的类如下:
package actualtest;
import test.CustomFrame;
import java.awt。*;
import javax.swing。*;
// http://stackoverflow.com/a/11150286/1057230
public class CustomPanel扩展JPanel
{
private CustomFrame frame;
public CustomPanel()
{
setOpaque(true);
setBackground(Color.DARK_GRAY);
JLabel label = new JLabel(
我是Java Swing中的JLabel,JLabel.CENTER);
label.setOpaque(false);
label.setForeground(Color.WHITE);
add(label);
}
private void createAndDisplayGUI()
{
frame = new CustomFrame(Testing Jar Implementation);
frame.setContentPane(this);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
@Override
public Dimension getPreferredSize()
{
return(new Dimension(500,300));
}
public static void main(String ... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new CustomPanel()。createAndDisplayGUI();
}
});
}
}
编译顺序与以前完全一样,如下所示:
C:\Mine\JAVA\J2SE\src\testingjar> javac - d类src\test\CustomFrame.java
C:\Mine\JAVA\J2SE\src\testingjar> cd类
C:\\ \\Mine\JAVA\J2SE\src\testingjar\classes> jar -cfm ..\test.jar ..\manifest.txt test
C:\Mine\\ \\ JAVA\J2SE\src\testingjar\classes> cd ..
C:\Mine\JAVA\J2SE\src\testingjar> javac -classpath test.jar -d classes src\actualtest\CustomPanel.jav
a
C:\Mine\JAVA\J2SE\src\testingjar> cd classes
C:\Mine\JAVA\J2SE\src\testingjar\classes> java actualtest.CustomPanel
仍然是相同的输出,我是
最新编辑
我刚刚发现,有时候事情的作用,而不是以后,当使用JAR文件时,您必须指定包含点运算符的类路径以及。
,如
C:\Mine\JAVA\J2SE\src\testingjar> java -classpath test.jar;。 realtest.CustomPanel
这是当我带来 actualtest $ c $在$ code> testingjar
文件夹中,c> 包
,则上述命令用于此情况。
I have a plugin system for my Java app. I invoke an external class with the URL class loader. That part works well, both when my application is run as class files, and when my application is in JAR form. The problem that I am running into is, the plugin files can run their own independent code just fine, but they create a JPanel. When I try to add that JPanel to the JPanel that's in the main application class, I get a null pointer exception referencing the main class. (com.cpcookieman.app.Main) But that doesn't happen if I run the class files for the application, only when it's packaged. How can I solve that?
Why does my code being packaged into a jar file prevent external classes from accessing classes inside the jar?
EDIT: As requested, the stack trace.
java.lang.NullPointerException
at TestPlugin2.Main.<init>(Main.java:23)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance0(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at com.cpcookieman.ph.PluginLoader$2.run(PluginLoader.java:74)
at java.lang.Thread.run(Unknown Source)
EDIT 2: The class loading code
String pluginsPath;
if (Main.os.equals("Windows"))
{
pluginsPath = "C:\\plugins\\";
}
else
{
pluginsPath = "~/plugins/";
}
File file = new File(pluginsPath);
if (!file.exists())
{
System.out.println("DEBUG: Plugin path could not be found!");
}
try
{
URL url = file.toURI().toURL();
final URL[] urls = new URL[]{url};
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
ClassLoader cl = new URLClassLoader(urls);
Class plugin = cl.loadClass(text + ".Main");
plugin.newInstance();
close();
}
**snip catch statements**
}
}).start();
}
**snip catch statements**
The plugin loads up using it's constructor, and creates a panel to be added to the frame that's inside one of the classes inside the JAR file. The JAR is the main application, if anyone's confused about that.
解决方案 I really don't know the structure of your project, though I had made a small example code for you to look at, have a look.
Consider that my project is placed at C:\Mine\JAVA\J2SE\src\testingjar>
Inside this my directory structure is as below :
testingjar
|
----------------------------------
| | | |
classes src manifest.text test.jar(this .jar we be creating shortly)
| |
| (Almost same as classes folder, just .java files)
---------------
| |
actualtest test
| |
*.class *.class
My Class that will become a part of a .jar file, is as given below :
package test;
import java.awt.*;
import javax.swing.*;
public class CustomPanel extends JPanel
{
public CustomPanel()
{
setOpaque(true);
setBackground(Color.DARK_GRAY);
JLabel label = new JLabel(
"I am a JLabel from Java Swing", JLabel.CENTER);
label.setOpaque(false);
label.setForeground(Color.WHITE);
add(label);
}
@Override
public Dimension getPreferredSize()
{
return (new Dimension(500, 300));
}
}
I compiled this class with the following command :
C:\Mine\JAVA\J2SE\src\testingjar>javac -d classes src\test\CustomPanel.java
Now Creating Manifest File for the JAR File, the contents of which are as follows :
Main-Class: test.CustomPanel
Do remember the space between colons (:) and the package name i.e. test, and after CustomPanel, Press Enter and save the file.
Now for creating a JAR File named test.jar
, I wrote these commands :
C:\Mine\JAVA\J2SE\src\testingjar>cd classes
C:\Mine\JAVA\J2SE\src\testingjar\classes>jar -cfm ..\test.jar ..\manifest.txt test
Now the class that will use this .jar file will be like this :
package actualtest;
import test.CustomPanel;
import java.awt.*;
import javax.swing.*;
public class ActualImplementation
{
private void createAndDisplayGUI()
{
JFrame frame = new JFrame("Testing Jar Implementation");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CustomPanel panel = new CustomPanel();
frame.setContentPane(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new ActualImplementation().createAndDisplayGUI();
}
});
}
}
I compiled this by writing these commands :
C:\Mine\JAVA\J2SE\src\testingjar\classes>cd..
C:\Mine\JAVA\J2SE\src\testingjar>javac -classpath test.jar -d classes src\actualtest\ActualImplement
ation.java
Now to run I wrote these commands :
C:\Mine\JAVA\J2SE\src\testingjar>cd classes
C:\Mine\JAVA\J2SE\src\testingjar\classes>java actualtest.ActualImplementation
OUTPUT
Do match the steps, might be you be missing something, since it's working fine on my side.
LATEST EDIT : As asked, I did that the other way around, now JFrame
is inside the .jar file and JPanel
is using it.
The class that will become the part of the .jar file is as follows :
package test;
import java.awt.*;
import javax.swing.*;
public class CustomFrame extends JFrame
{
public CustomFrame(String title)
{
super(title);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
Contents of the manifest.txt file, will change as follows :
Main-Class: test.CustomFrame
And the class which will use CustomFrame Class from the .jar file, is as follows :
package actualtest;
import test.CustomFrame;
import java.awt.*;
import javax.swing.*;
// http://stackoverflow.com/a/11150286/1057230
public class CustomPanel extends JPanel
{
private CustomFrame frame;
public CustomPanel()
{
setOpaque(true);
setBackground(Color.DARK_GRAY);
JLabel label = new JLabel(
"I am a JLabel from Java Swing", JLabel.CENTER);
label.setOpaque(false);
label.setForeground(Color.WHITE);
add(label);
}
private void createAndDisplayGUI()
{
frame = new CustomFrame("Testing Jar Implementation");
frame.setContentPane(this);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
@Override
public Dimension getPreferredSize()
{
return (new Dimension(500, 300));
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new CustomPanel().createAndDisplayGUI();
}
});
}
}
The compilation sequence, is very much the same as before, which is as follows :
C:\Mine\JAVA\J2SE\src\testingjar>javac -d classes src\test\CustomFrame.java
C:\Mine\JAVA\J2SE\src\testingjar>cd classes
C:\Mine\JAVA\J2SE\src\testingjar\classes>jar -cfm ..\test.jar ..\manifest.txt test
C:\Mine\JAVA\J2SE\src\testingjar\classes>cd..
C:\Mine\JAVA\J2SE\src\testingjar>javac -classpath test.jar -d classes src\actualtest\CustomPanel.jav
a
C:\Mine\JAVA\J2SE\src\testingjar>cd classes
C:\Mine\JAVA\J2SE\src\testingjar\classes>java actualtest.CustomPanel
Still the same output, I am getting.
LATEST EDIT :
I just found out, that sometimes this thing works, instead of the later, when using JAR Files, you have to specify the classpath including the dot operator as well .
, like
C:\Mine\JAVA\J2SE\src\testingjar>java -classpath test.jar;.; actualtest.CustomPanel
This is when I brought the actualtest
package
inside the testingjar
Folder, then the above command worked for this situation.
这篇关于Java:为什么代码打包成jar文件阻止外部类访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!