centos升级之后不能启动vmware的问题解决

前段时间centos增加了一个cr仓库,直接使用yum install centos-release-cr 就可以安装了。此仓库包括了centos自centos6.0以来的一系列更新。安装之后,使用yum update就可以更新系统了。更新之后,相对应的kernel从kernel-2.6.32-71升级到2.6.32-131.17.1.el6.i686。

重新启动之后,发现vmware启动不了,运行vmware之后,提示重新install,没问题,在界面上安装之后,能够启动vmware了。但不能启动monitor,即不能启动vmware player。显示错误信息如下所示:

May 19 13:45:41 xxx kernel: vmmon: disagrees about version of symbol smp_ops
May 19 13:45:41 xxx kernel: vmmon: Unknown symbol smp_ops

网上搜索之后,提示执行以下代码:

vmware-modconfig --console --install-all

仍不能解决,最后在redhat官方bug反馈区找到答案 https://bugzilla.redhat.com/show_bug.cgi?id=706216。在centos目录/usr/lib/vmware/modules/binary下删除有关于redhat的驱动包,在那个目录有很多已经编译好的二进制包。笔者直接执行删除全部,然后再执行重新配置,最后OK。整个执行代码为:

cd /usr/lib/vmware/modules/binary
rm -rf *
vmware-modconfig --console --install-all

至此,配置之后,vmware即能够重新正常启动了。以上代码当然要在root用户下执行了。笔者centos版本为centos6.0,vmware版本为vmware7.0。

JVM对于不同classLoader加载的对象之间default或protected字段的访问限制

    通常对于对象的default及protected访问限制,一般的说法即为只能由同包或子类才能访问。对于同包的类,是可以访问default及protected的字段的。但如下情况除外:
    如果一个由其它途径加载的类尝试访问同一个包中由其它加载器加载的类的受保护或默认级别字段时,将产生一个IllegalAccessError错误,即不允许访问指定的字段。
    即只有相同加载器之间才可以访问受保护字段。

验证程序如下所示:类Foo

public class Foo implements IFoo {
	protected int i = 2;
}

类Foo2将要访问Foo:

public class Foo2 {
	public static void redFoo() {
		Foo f = new Foo();
		System.out.println(f.i);
	}
}

    以下为执行验证的代码:

		MyClassLoader2 myClassLoader2 = new MyClassLoader2(T.class.getClassLoader());
		Class<?> clazz = myClassLoader2.loadClass("m_ylf.study.java.classLoad.Foo2");
//		Class<?> clazz2 = myClassLoader2.loadClass("m_ylf.study.java.classLoad.Foo");
		clazz.getDeclaredMethod("redFoo").invoke(null);

    在以上代码中,将由类加载器单独加载Foo2,而Foo仍由appClassLoader来加载。上面的程序即通过调用Foo2的redFoo方法来读取Foo类的受保护字段,并输出信息。执行结果如下所示:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
......
Caused by: java.lang.IllegalAccessError: tried to access field com.m_ylf.study.java.classLoad.Foo.i from class com.m_ylf.study.java.classLoad.Foo2
	at com.m_ylf.study.java.classLoad.Foo2.redFoo(Foo2.java:8)
	... 11 more

    即不能访问该字段,需要注意到的是,在以上的代码中,我们专门注释了使用myClassLoader加载Foo的代码。如果我们取消注释,即也叫myClassLoader来加载Foo,那么结果即能够正确的输出相对应的数字(具体输出结果就不再列出,可以单独测试)。
    需要注意的是,如果Foo中的字段i,本身就是public类型的,则该错误也不会发生。即这个约束只限制在default以及protected字段上。
    这也是为了将一个恶意的代码,加载到虚拟机,来尝试访问本来不能够被访问的信息,如标准java API中的受保护信息(标准API是由java 系统加载器来加载的)。
    以上的叙述取自《深入JVM虚拟机》,由笔者验证得出。

继续阅读“JVM对于不同classLoader加载的对象之间default或protected字段的访问限制”

深入理解jvm装载约束

    网上进行google或者baidu时,以及在使用tomcat或者其它框架时,经常碰到以下的问题:

ava.lang.LinkageError: loader constraint violation: when resolving field  XXXXXX 
have different Class objects for that type

    这种问题在使用jbmp,或者websphere时经常会出现,一般的解决方法就是说有的包重复了,删除一些jar包就可以了。
    问题是解决了,但问题产生的根源在哪,我们需要知道这个问题。在阅读了《深入JVM虚拟机》之后,中间有提到一段话,这段话揭示了问题产生的本质在于在一个方法体中同一个类被多个不同的classLoader所加载了,即在声明时的类与引用的类(同一个类)在加载时,却是由不同的classLoader所加载的:

如果引用的类型和被引用的类型并非由同一个初始装载器装载,虚拟机必须确保在字段或者方法描述符中所提及的类型
在不同的命名空间中保持一致。

    这句话理解起来非常的困难,简单一点理解可以由下面的说明来理解:

  1. 类A中有一个字段a,它的类型为X
  2. 类B中有一个字段b,它的类型也为X
  3. 类A由classLoaderA所加载,类B由classLoaderB所加载
  4. 执行赋值语句A.a = B.b,由于这两个类型均为X,可以执行,但是有一个要求,这个要求就是在A中所装载类X的装载器必须和在B中装载类X的装载器相同,否则赋值语句失败

    为什么会产生上面的输出,我们可以来看一个以下的代码

继续阅读“深入理解jvm装载约束”